Referrer-Policy controls how much information about a source page a browser sends when requesting another URL. Set an explicit policy on your deployed pages, then inspect the outgoing request. A response header being present does not establish that every link or resource sends the information you intended.
For a public documentation site or student portfolio, strict-origin-when-cross-origin is a useful starting point. Choose a stricter value when the destination should receive less information. This guide covers that choice, deployment, overrides, and browser testing. Use the broader website security headers checklist for the surrounding transport and content policies.
Referrer-Policy launch checklist
- Choose what same-origin and external destinations should receive.
- Set the policy in the layer that produces the public response.
- Inspect a final HTML response with a GET request.
- Review document, link, and request-specific overrides.
- Follow real links and inspect their outgoing
Refererheaders. - Save a focused browser regression test for the intended behavior.
- Audit the public URL and resolve missing-header evidence before release.
Understand Referrer-Policy and the Referer header
The response header uses the spelling Referrer-Policy; the historical request header is spelled Referer. MDN's Referer reference explains that the request can identify the page that initiated navigation or a resource load. A referrer may include a path and query string, but excludes the fragment and URL credentials.
For example, imagine this source page:
https://example.com/guides/launch?campaign=class-project#checks
A full referrer can expose /guides/launch?campaign=class-project. An origin-only referrer is https://example.com/. No referrer means the request omits the header. Use harmless fixture values during testing so screenshots and logs contain no personal data.
Do not place passwords, access tokens, or private form values in URLs. Review that separately using the website form testing checklist; a referrer policy cannot clean up information already captured by your own application or telemetry.
Choose strict-origin-when-cross-origin or a stricter policy
The Referrer Policy specification defines the choices below for an HTTPS source page:
strict-origin-when-cross-origin: send the full referrer to the same origin, only the origin to another HTTPS origin, and no referrer on an HTTPS-to-HTTP downgrade.same-origin: send the full referrer only to the same origin; omit it for external destinations.strict-origin: send only the origin to HTTPS destinations, including same-origin requests; omit it on a downgrade.no-referrer: omit referrer information for all requests governed by the policy.
Same origin requires the same scheme, host, and port. A documentation subdomain is a different origin. Write down expected results for each destination before implementing the policy.
For a public launch guide that needs internal referral paths and external domain attribution, start with:
Referrer-Policy: strict-origin-when-cross-origin
MDN's Referrer-Policy reference identifies this as the modern default. An explicit value still gives your team a policy to review and test. Missing the header does not by itself prove that a browser leaked full URLs. Avoid unsafe-url as a troubleshooting shortcut: it permits path and query disclosure across origins, including downgrades.
Set Referrer-Policy in the response layer
Configure the application, reverse proxy, or hosting response rules that own the final HTML. For an existing Nginx server block, the directive is:
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
Nginx's headers module documentation explains that always applies the header regardless of response status. Review nested locations too: under the default inheritance rules, a location with its own add_header directives does not inherit the parent set. Merge this into your existing configuration and validate it before reloading.
Keep one clear owner for the policy. If both application middleware and a CDN add it, inspect the delivered result and remove accidental duplication. Do not add the example blindly to an unrelated server or replace the rest of your security headers.
When you control HTML but cannot configure responses, MDN's referrer policy configuration guide describes the document-level alternative. Put it early in the head, before resources that need the policy:
<meta name="referrer" content="strict-origin-when-cross-origin">
Prefer the response header when you own that layer. Keep the HTML declaration aligned with it; conflicting configuration makes later debugging harder. An HTTP-header-only scanner may still report the header missing when HTML supplies a policy.
Inspect the deployed response with GET
Request a representative public page rather than relying on a local configuration file:
curl --silent --show-error --location \
--dump-header - --output /dev/null \
'https://example.com/guides/launch?campaign=class-project'
The curl manual documents these options: follow redirects, print response headers, and discard the body. This sends a GET rather than a HEAD request. Read every response block, then identify the final HTML response and its policy.
Repeat for a nested page and an error page your deployment serves. If results differ, inspect the route's middleware, proxy location, and CDN rules. Use the canonical URL and redirects guide when the hostname or redirect destination differs from your intended public URL.
This command verifies delivery. It does not run a browser or establish which referrer a subsequent link click will send.
Check overrides when the browser sends something unexpected
Inspect the source page's HTML and the particular element that initiated the request. MDN documents referrerpolicy on elements such as links and images. A link can deliberately suppress the referrer:
<a href="https://docs.example.net/" referrerpolicy="no-referrer">
Partner documentation
</a>
Also review rel="noreferrer". The MDN noreferrer reference explains that it omits referrer information and also provides noopener behavior. An external link with that relation will not provide domain attribution just because the page header allows it.
For script-initiated requests, search the responsible code for a referrerPolicy option. Record whether an exception is intentional before changing it. Do not remove a privacy choice merely to make an analytics dashboard show more detail.
DevTools may display strict-origin-when-cross-origin beside a failed request. That label alone is not an error. Inspect status, response, and console details. CORS governs whether scripts can access cross-origin responses; changing the referrer policy does not grant that access. Use the JavaScript console errors guide to trace the actual failure.
Test outgoing Referer headers in a browser
Open the source page in a clean browser context. In the Network panel, enable preserved logs, follow a real link, and inspect the destination request's Request Headers. Chrome's Network reference documents header inspection and preserving requests across navigation.
For the example source and strict-origin-when-cross-origin, check:
- A link to
https://example.com/docssends the source URL with its query and without#checks. - A link to an HTTPS destination on another origin sends
https://example.com/. - A link with
referrerpolicy="no-referrer"sends noRefererheader.
Use destinations you control. Check receiving-server logs if you need confirmation of what arrived. Repeat in supported browsers and privacy configurations; extensions or browser settings may further restrict disclosure. An absent header is a case to investigate against your contract, not proof of a deployment failure.
Add a focused Referrer-Policy regression test
This Playwright example assumes your owned source page has two ordinary, same-tab links named Internal documentation and Partner documentation. Replace the domains, routes, and names with real test destinations. Neither link should have an override for this baseline test.
import { expect, test } from "@playwright/test";
const source = "https://example.com/guides/launch?campaign=class-project#checks";
const fullReferrer = source.split("#")[0];
const cases = [
{
name: "Internal documentation",
destination: "https://example.com/docs",
expected: fullReferrer,
},
{
name: "Partner documentation",
destination: "https://docs.example.net/",
expected: new URL(source).origin + "/",
},
];
for (const scenario of cases) {
test(`referrer contract: ${scenario.name}`, async ({ page }) => {
const response = await page.goto(source);
expect(response).not.toBeNull();
expect(response!.ok()).toBe(true);
expect(await response!.headerValue("referrer-policy"))
.toBe("strict-origin-when-cross-origin");
const [request] = await Promise.all([
page.waitForRequest((request) =>
request.isNavigationRequest() &&
request.frame() === page.mainFrame() &&
request.url() === scenario.destination,
),
page.getByRole("link", { name: scenario.name, exact: true }).click(),
]);
expect(await request.headerValue("referer")).toBe(scenario.expected);
});
}
Playwright's request API exposes the observed header value. Run this with a normal browser context; do not inject a Referer header in test configuration. Add separate cases for intentional suppression, popups, or redirects rather than assuming this baseline covers them. Keep the test with your website regression checks and update expected values when the policy changes deliberately.
Check the public release with Slop Audit
After deploying the policy, run Slop Audit on your public URL. Its static audit records observed Referrer-Policy and Permissions-Policy response headers in a combined finding. Use the evidence to identify a missing header, fix its response layer, and rescan the same route.
That finding checks whether both headers are present. It does not validate their directive values, resolve HTML or element overrides, or verify the outgoing referrer at each destination. A pass is useful delivery evidence alongside your browser tests. Save both with the release so a later configuration regression has a specific result to compare against.