How long should you run CSP in report-only mode before enforcing?
The honest answer: 1 to 4 weeks of representative traffic. What representative actually means, the three signals that tell you discovery is done, and the traps of both stopping too early and never enforcing at all.
Every CSP rollout guide agrees on the sequence: ship Content-Security-Policy-Report-Only, watch the violation reports, then move the policy to the enforced header. What the guides rarely tell you is when to stop watching.
The honest answer is 1 to 4 weeks of representative traffic. And “representative” carries more weight than the number: the window must contain at least one full deploy cycle, both weekday and weekend traffic, any marketing campaigns or A/B tests currently live, and enough volume for the long tail of browsers to appear. When the criteria below are met, enforce, whether that took nine days or thirty. The calendar does not decide. The coverage does.
If you are still upstream of this question, start with what a Content Security Policy is and come back.
Why “representative” beats any number of days
One quiet Tuesday proves nothing. It tells you what your site loads on a quiet Tuesday, which is the least interesting day it has.
Think about what your window has to catch:
- Your deploy cadence. If you ship weekly, a five-day window can miss an entire release, and releases are exactly when new scripts appear. The window should span at least one full cycle, ideally two.
- The weekday/weekend split. Weekend traffic often skews toward consumer devices, older browsers, different pages. B2B sites see the inverse. Either way, Saturday’s violations are not Tuesday’s.
- Campaigns and A/B tests. Marketing landing pages pull in tracking pixels and tag-manager containers that only fire for certain UTM parameters. An A/B test means half your users load scripts the other half never see. If a campaign launches the week after you enforce, its scripts get blocked on day one.
- The browser long tail. Chrome on desktop shows up in the first hour. The Safari on a four-year-old iPad shows up in week two.
How do you know you have collected enough?
Three signals, and you want all three.
The new-violation rate has flatlined. Not the raw report count, which just tracks traffic. Watch distinct directive-and-origin pairs per day. The curve climbs fast in the first days, bends, then goes flat. Several consecutive days adding nothing new means discovery has converged.
Every remaining violation is explained. Each one lands in one of three buckets: fixed (the inline handler became an external file, the script got a nonce), allowed (the origin was added to the policy on purpose), or classified as noise (browser extensions inject scripts into your pages, and those report against your policy despite not being your code). Zero violations is not achievable. Zero unexplained violations is.
Every page type has been exercised. Checkout, password reset, error pages, the admin panel nobody visits. Reports carry the document URL, so this is checkable: group by page and look for silence. A page type with no reports at all either loads nothing interesting or was never visited during the window. Go click through it yourself before assuming the former.
The traps of stopping too early
Some things only surface on their own schedule, and they are the classic post-enforcement incidents:
The monthly batch job. The invoicing page that renders on the 1st, the payroll export, the quarterly report generator. A three-week window that misses the 1st misses them entirely.
Seasonal pages. Sale banners, holiday landing pages, the countdown widget someone resurrects every November. If it did not render during your window, its scripts are not in your policy.
Geo-specific content. Consent management scripts differ by country. A payment provider that only loads for one market reports only from that market. If 95% of your discovery traffic is domestic, your Brazilian checkout is undiscovered.
You do not have to wait for all of these. But decide consciously: either extend the window to cover them, or enforce anyway and commit to watching reports closely when the batch job next fires. What you cannot do is be surprised.
The trap of never stopping
The opposite failure is more common and quieter. We have watched teams collect reports for over a year without ever enforcing. Report-only feels productive: the dashboard fills, violations get triaged, tickets get closed. Meanwhile a policy that blocks nothing protects nothing. An injected script executes exactly as well under report-only as under no policy at all.
If your team has been in report-only for more than two months, the blocker is rarely data. Name what is actually preventing enforcement, fix that, and put a date in the sprint.
Is one week enough? Depends on the site
Report URI’s policy wizard is built around roughly seven days of collected traffic (per their published guidance, as of August 2026). A fixed week is a bet that your site’s full behavior shows up in seven days: true for some high-traffic sites, and quietly wrong for everyone whose monthly billing job, seasonal pages or slow deploy cadence fall outside the window.
The number breaks down completely for quiet sites. An internal tool with 40 users needs weeks to accumulate the browser and page coverage a retailer sees in a day. CentralCSP’s Builder accepts any report window from 1 to 90 days for exactly this reason: retention is 90 days on every tier, so a low-traffic site can simply let reports pile up until the flatline is real, then build the policy from the full window.
The checklist to graduate to enforcement
- No new distinct directive-and-origin pairs for 5 to 7 consecutive days, including a weekend.
- At least one full deploy cycle inside the window.
- Every open violation is fixed, allowed, or tagged as extension noise.
- Every page type shows reports, or someone exercised it manually.
- Known periodic jobs (monthly billing, seasonal pages) either observed or consciously deferred with a plan.
- A named person owns the first 48 hours after the flip.
All boxes ticked, you are done discovering. The flip itself has its own mechanics (staged rollout, keeping the report-only header running alongside the enforced one, rollback criteria), and we keep those in the report-only to enforced migration runbook. If that named person is a backend developer who inherited this on top of their sprint, running a solid CSP without a dedicated security engineer is the workload version of the same plan.
Frequently asked questions
Is one week of CSP reports enough before enforcing?
Sometimes. A week is enough if it contains at least one full deploy cycle, a weekend, any marketing campaigns or A/B tests currently running, and reports from every page type on the site. A high-traffic site that deploys daily can hit that bar in seven days. A low-traffic internal tool usually cannot, and should extend the window rather than enforce on thin data.
How much traffic do I need before enforcing a CSP?
There is no absolute number. Coverage matters more than volume: every page type visited, the long tail of browsers represented, and the new-violation rate flat for several consecutive days. A site with 500 daily visitors just takes longer to reach the same coverage as a site with 500,000. Tools that build policies from reports should let you widen the window accordingly. CentralCSP accepts any window from 1 to 90 days.
What if my violation rate never reaches zero?
It never will, and that is not the goal. Browser extensions inject scripts into your pages and those show up as violations against your policy even though they are not your code. The graduation criterion is zero unexplained violations: every remaining report is either fixed, deliberately allowed in the policy, or classified as extension noise.
Can I just stay in report-only mode permanently?
You can, and plenty of teams accidentally do, but a report-only policy blocks nothing and therefore protects nothing. An attacker injecting a script does not care that a report was filed about it. Report-only is a discovery phase with an exit, not a security posture.