X-Robots-Tag
The X-Robots-Tag HTTP header carries the same directives as the robots meta tag, so you can noindex PDFs, images, and videos. Apache, Nginx, and Cloudflare configs plus how to verify with curl.
1 evidence signal on this page
- Related live toolHTTP Header Checker
The X-Robots-Tag is the HTTP-header twin of the robots meta tag: same directive vocabulary (noindex, nofollow, nosnippet, and the rest), but delivered in the response header so it works on files with no HTML <head> — PDFs, images, videos, anything. You set it at the server (Apache, Nginx, or a CDN/Worker), so one rule can noindex every PDF on the site. The single most common mistake is also blocking that file in robots.txt — which hides the header, so Google never crawls the file to read the noindex and the directive is ignored. Verify the live header with curl -I, and watch for a CDN serving a different header than your origin (the 'Noindex detected in X-Robots-Tag' Search Console failure).
TL;DR — The X-Robots-Tag is a way to tell search engines “don’t index this file” — but instead of putting a tag in the page’s HTML, it’s sent in the server’s response. That matters because some files (PDFs, images, videos) have no HTML to put a tag in. So when you need to keep a PDF out of Google, the X-Robots-Tag is how you do it.
Evidence for this claim Google supports robots directives in the X-Robots-Tag HTTP response header, including for non-HTML resources such as PDFs. Scope: Google crawling and indexing controls delivered by HTTP header. Confidence: high · Verified: Google Search Central: X-Robots-Tag Evidence for this claim Google must be allowed to crawl a resource to discover and apply its X-Robots-Tag noindex rule. Scope: A robots.txt block can prevent Google from seeing the response header. Confidence: high · Verified: Google Search Central: Combining crawling and indexing rules
What it is
You’ve probably seen the robots meta tag — a little snippet in a page’s HTML
that says <meta name="robots" content="noindex" /> to keep that page out of
search. The X-Robots-Tag does the exact same job, but it travels in the HTTP
response header the server sends back, not in the page’s HTML.
Why would you need that? Because some things on your site aren’t HTML pages.
A PDF has no <head> section. Neither does an image or a video file. There’s
nowhere to put a meta tag. So if you want to keep a PDF out of Google’s index, you
can’t use the meta tag — you use the X-Robots-Tag header instead.
When you’d reach for it
- You have a PDF (a price list, an old whitepaper, a gated download that leaked) showing up in search and you want it gone.
- You want to noindex a whole class of files at once — every PDF on the site — with one rule, instead of editing them one by one.
- You’re dealing with images or videos you don’t want indexed on their own.
For a normal HTML page, you’d just use the meta tag — it’s easier. The X-Robots-Tag is for the cases where the meta tag can’t reach.
The one mistake everyone makes
Here’s the trap, and it catches people constantly. They want a PDF gone, so they
do two things: they block it in robots.txt and they add an X-Robots-Tag
noindex. Belt and suspenders, right?
Wrong. Blocking it in robots.txt stops Google from ever fetching the file — so Google never sees the noindex header you carefully set. The directive gets ignored, and the PDF can stay in search. The rule is: to noindex a file, you have to let Google crawl it so it can read the header. Don’t block it.
How to check it
You (or a developer) can confirm the header is live with a single command:
curl -I https://example.com/file.pdf. That prints the response headers without
downloading the file, and you look for the X-Robots-Tag line. There’s a copy-paste
version in the Scripts tab.
Want the actual server config for Apache, Nginx, and Cloudflare — plus how to target just Googlebot and verify the live header? Switch to the Advanced tab.
TL;DR — The X-Robots-Tag is the HTTP-header delivery of the same directive vocabulary as the robots meta tag — “Any rule that can be used in a robots
Evidence for this claim Google supports robots directives in the X-Robots-Tag HTTP response header, including for non-HTML resources such as PDFs. Scope: Google crawling and indexing controls delivered by HTTP header. Confidence: high · Verified: Google Search Central: X-Robots-Tag Evidence for this claim Google must be allowed to crawl a resource to discover and apply its X-Robots-Tag noindex rule. Scope: A robots.txt block can prevent Google from seeing the response header. Confidence: high · Verified: Google Search Central: Combining crawling and indexing rulesmetatag can also be specified as anX-Robots-Tag.” It exists for one big reason: non-HTML resources (PDFs, images, videos) have no<head>, so the header is the supported way to noindex them. You set it server-side (Apache<FilesMatch>, Nginxadd_header, or a Cloudflare Transform Rule / Worker), so one rule covers a whole file type. Optionally target a crawler withX-Robots-Tag: googlebot: noindex; with no user-agent it applies to all of them. The spine caveat, shared with the meta tag: the file must be crawlable — a robots.txt block hides the header, so the noindex is “not found and… therefore ignored.” Verify withcurl -I, and watch for CDN-vs-origin header drift.
What the X-Robots-Tag actually is
The X-Robots-Tag is the HTTP response header version of the robots <meta>
tag. That’s the whole concept. Google is explicit that the two are interchangeable
in vocabulary: “The X-Robots-Tag can be used as an element of the HTTP header
response for a given URL. Any rule that can be used in a robots meta tag can also
be specified as an X-Robots-Tag.” A response carrying it looks like this:
HTTP/1.1 200 OK
Date: Tue, 25 May 2010 21:42:43 GMT
(…)
X-Robots-Tag: noindex
(…)So if you already understand the robots meta tag, you already understand the
directives here — noindex, nofollow, nosnippet, and the rest behave
identically for Google. The only thing that changes is the delivery mechanism:
header, not HTML.
That equivalence is a Google-documented contract, not a universal web standard — the X-Robots-Tag is a de facto header with no IETF specification backing it. Google says so directly on the same doc: “It is possible that these rules may not be treated the same by all other search engines.” Treat “same directives as the meta tag” as true for Google (and, per the Other Engines section below, largely true for Bing’s core set) — not as a guarantee for every crawler, including AI crawlers, that might read this header.
Why it exists — non-HTML files
The defining use case is files that have no HTML <head> to drop a meta tag into.
Google’s guidance is direct: “To block indexing of non-HTML resources, such as PDF
files, video files, or image files, use the X-Robots-Tag response header
instead.” That’s the headline. A PDF, an image, or a video can’t carry a
robots meta tag — there’s nowhere to put it — so the header is the supported route
to noindex them.
There’s a second, quieter reason: it’s set server-side, so one rule can apply a
directive to an entire class of files (every .pdf on the site) or site-wide,
without you editing each resource. That’s powerful, and — as we’ll see — also where
the foot-guns live.
Worked example — noindexing a single PDF: say
https://example.com/whitepapers/old-report.pdf is showing up in search and you
want it gone. Two conditions both have to hold: (1) the resource must stay
crawlable — no Disallow on it in robots.txt — and (2) the server response
for that exact URL must carry X-Robots-Tag: noindex. Set the rule (Apache/Nginx/
Cloudflare examples below), confirm with curl -I that the live response
actually returns the header (see the verification section), then wait for
Google to recrawl the URL. Skip either condition and the PDF stays indexed: skip
crawlability and Google never reads the header; skip the header and there’s
nothing telling Google to drop it.
Do not turn “non-HTML” into “wrong file type.” Google publishes a broad list of
indexable file types,
including PDF, common office formats, text, XML, and several source-code formats.
A crawler should preserve three separate observations: the URL extension, the
declared Content-Type, and the bytes actually returned. A mismatch is a delivery
warning; a legitimate supported document is not an HTML-page failure and should have
HTML-only checks marked not applicable. Use X-Robots-Tag or an HTTP Link canonical
when those controls are needed for the non-HTML resource.
Size limits also need an engine-and-basis label. Google’s March 2026 crawler update documents a 2 MB per-URL cutoff for Googlebot (Search), a 64 MB PDF cutoff, and a 15 MB default for unspecified Google crawler clients. Those are decimal MB resource limits, not interchangeable with a tool’s decoded-body MiB safety cap. See Google’s current crawler limits before turning a product limit into an SEO diagnosis.
Meta tag vs X-Robots-Tag — when to use which
The decision is simple once you frame it around the <head>:
- HTML page you control the markup of → use the robots meta tag. It’s easier to set, easier to read, and per-page.
- Non-HTML file (PDF, image, video, feed) → use the X-Robots-Tag header.
There’s no other option; these have no
<head>. - You’d rather control it server-side / site-wide, or you can’t easily touch each page’s HTML (CDN, app layer) → the header is the cleaner lever even for HTML.
They’re not rivals and one isn’t “stronger” — same directives, different reach.
The directives you can use
The X-Robots-Tag accepts the same directive vocabulary as the meta tag. The full supported set:
noindex— don’t index this resource.nofollow— don’t follow links from it.none— shorthand fornoindex, nofollow.all— no restrictions (the default).nosnippet— no text snippet or video preview in results (the page-level cousin ofdata-nosnippet, which scopes it to part of a page).max-snippet: [number]— cap the snippet length.max-image-preview: [none | standard | large]— cap the preview image size.max-video-preview: [number]— cap the video preview length in seconds.noarchive— no cached link.noimageindex— don’t index images on the page.notranslate— don’t offer translation in results.indexifembedded— don’t index this resource on its own, but do allow indexing where it’s embedded (e.g. in an iframe). Pair it withnoindex.unavailable_after: [date/time]— drop the URL from results after a date. The date must be in a widely adopted format (RFC 822, RFC 850, or ISO 8601), e.g.:
X-Robots-Tag: unavailable_after: 25 Jun 2010 15:00:00 PSTPresenting the table once is deliberate: it’s the same list shared by the meta tag, which is the cleanest way to think about the relationship between the two.
Targeting a specific crawler
You can optionally prefix the directive with a user-agent token: Google notes the header “may optionally specify a user agent before the rules,” and that “Rules specified without a user agent are valid for all crawlers. The HTTP header, the user agent name, and the specified values are not case sensitive.” So this is valid syntax to noindex only for Google:
Evidence for this claim Google's header syntax permits an optional crawler name before a rule list, and Google treats header names, crawler names and directive values as case-insensitive. Scope: production HTML and HTTP responses Confidence: high · Verified: Robots meta tag, data-nosnippet, and X-Robots-Tag specificationsX-Robots-Tag: googlebot: noindexAnd you can stack lines for different bots. (One note on attribution: Google’s own
documented example of per-crawler targeting uses X-Robots-Tag: googlebot: nofollow paired with X-Robots-Tag: otherbot: noindex, nofollow — so
googlebot: noindex is correct, supported syntax, just not the verbatim line in
Google’s sample.)
Multiple rules and conflicting directives
You’re not limited to one directive per response. Google documents this
directly: “Multiple rules may be combined in a comma-separated list or in
separate meta tags. These rules are case-insensitive.” — the same is true for
the header: send X-Robots-Tag: noindex, nofollow as one comma-separated line,
or repeat the header field (X-Robots-Tag: noindex on one line,
X-Robots-Tag: nofollow on another). Both are valid; the server config examples
below use the comma-separated form.
When two rules would conflict, Google resolves it in favor of the tighter
restriction: “In the case of conflicting robots rules, the more restrictive
rule applies. For example, if a page has both max-snippet:50 and nosnippet
rules, the nosnippet rule will apply.” That’s Google’s documented behavior —
the same “not treated the same by all other search engines” caveat above
applies to conflict resolution too, so don’t assume every crawler picks the
stricter rule the same way.
How to set it (server config)
These are known-good, battle-tested patterns I’d reach for — treat every snippet
below as an environment-specific example, not a portable recipe: inheritance
rules, route matching, redirects, response status codes, and any CDN or
application layer in front of the server can all change what actually reaches
the crawler. Confirm the delivered header on your own stack before shipping,
not just the config file. Configs and snippets are in the Scripts tab,
copy-paste ready, for Apache (<FilesMatch> + mod_headers), Nginx (location
add_header), and Cloudflare (a Transform Rule or a Worker). The short version: one rule, matched on the file extension, setsX-Robots-Tag: noindexon every file of that type. To target a single crawler, the user-agent token goes inside the header value (Header set X-Robots-Tag "googlebot: noindex"), not as a separate mechanism.
The #1 mistake — don’t block the file in robots.txt
This is the spine of the whole topic, so I’ll be loud about it. People who want a
PDF gone often do two things at once: block it in robots.txt and set
X-Robots-Tag: noindex. That defeats itself. Google has to crawl the file to read
the header — and the robots.txt block stops the crawl.
Google’s own wording: “robots meta tags and X-Robots-Tag HTTP headers are discovered when a URL is crawled. If a page is disallowed from crawling through the robots.txt file, then any information about indexing or serving rules will not be found and will therefore be ignored.” And the corollary: “If indexing or serving rules must be followed, the URLs containing those rules cannot be disallowed from crawling.”
Restated for noindex specifically: “For the noindex rule to be effective, the
page or resource must not be blocked by a robots.txt file, and it has to be
otherwise accessible to the crawler. If the page is blocked by a robots.txt file or
the crawler can’t access the page, the crawler will never see the noindex rule,
and the page can still appear in search results.” This is the same
crawling-vs-indexing distinction that runs through robots.txt and the meta
tag: robots.txt controls crawling; the X-Robots-Tag controls indexing; and a
crawl block hides the indexing rule. To deindex a PDF: allow crawling, serve
X-Robots-Tag: noindex, and wait for the re-crawl.
(Note the flip side too: a robots.txt Disallow on its own doesn’t deindex a file
either — a blocked PDF can still be indexed if other pages link to it, just without
a snippet. Blocking and noindexing solve different problems.)
How to verify it with curl
Don’t trust that a config “should” work — check the live header. curl -I (or
curl -sI … | grep -i x-robots-tag) prints the response headers without
downloading the body:
curl -sI https://example.com/file.pdf | grep -i x-robots-tagYou can also spoof the bot view to see what Googlebot would get
(curl -A "Googlebot" -sI …). Most guides point you at a browser extension or
Screaming Frog for this; curl is faster and scriptable, and full commands are in
the Scripts tab.
One caveat on -I: it sends a HEAD request, and a server or CDN rule that only
fires on GET won’t show up in a HEAD response. Treat curl -I as a fast first
check, not the final word — confirm the same header on a real curl GET
request (curl -sD - -o /dev/null https://example.com/file.pdf | grep -i x-robots-tag), and check it after following redirects and on the public
CDN-fronted URL, not just origin.
Watch for CDN-vs-origin drift
Because the header is set server- and CDN-side, the value Googlebot receives can
differ from what your origin emits — an edge rule can add, strip, or cache a
header. The real-world failure mode here is the “Noindex detected in
X-Robots-Tag” message in Search Console: a CDN or edge config serving an
X-Robots-Tag: noindex — even briefly or by mistake — gets logged by Google as a
noindex signal and can deindex pages you never meant to touch. The lesson: always
curl -I the public URL behind the CDN, not just origin, and treat edge rules
with the same care as origin config.
Other engines
Bing supports the X-Robots-Tag header and broadly the same core directives —
noindex, nofollow, noarchive/nocache (Bing uses nocache as a synonym for
noarchive), nosnippet, and the preview-limit directives. If you need Bing’s
exact supported list, confirm it on Bing’s live help page — their documentation is
JavaScript-rendered and worth eyeballing directly before relying on a specific
directive.
Where this sits
The X-Robots-Tag is the non-HTML half of on-page indexing control: the robots meta tag for pages, this header for everything else. It leans on the same noindex, nosnippet / max-snippet / max-image-preview vocabulary, and it depends on crawling being allowed — which ties it straight back to robots.txt and the broader indexing story. If you came here from the crawling side, the takeaway is the caveat; if you came from the meta-tag side, the takeaway is that the same directives reach PDFs and media through the header.
AI summary
A condensed take on the Advanced version:
- What it is: the X-Robots-Tag is the HTTP response header version of the
robots meta tag — “Any rule that can be used in a robots
metatag can also be specified as anX-Robots-Tag.” Same directives, different delivery — for Google specifically; Google itself notes other search engines may not treat the rules the same way. - Why it exists: non-HTML files (PDFs, images, videos) have no
<head>, so the header is the supported way to noindex them — “use theX-Robots-Tagresponse header instead.” Requires the resource to stay crawlable, not just the header set. - Directives: the full meta-tag vocabulary —
noindex,nofollow,none,all,nosnippet,max-snippet,max-image-preview,max-video-preview,noarchive,noimageindex,notranslate,indexifembedded,unavailable_after. - Multiple rules: combine directives in a comma-separated list or repeated header lines; Google resolves conflicts by applying the more restrictive rule.
- Set it server-side: Apache
<FilesMatch>+mod_headers, Nginxadd_header, or a Cloudflare Transform Rule / Worker — one rule per file type. Treat every snippet as environment-specific (inheritance, redirects, status codes, and CDN/app layers can all change what’s actually delivered) — for example, Nginx stops inheriting a parent’sadd_headeronce a childlocationblock sets its own. - Per-crawler:
X-Robots-Tag: googlebot: noindex; no user-agent token = all crawlers; names/values are case-insensitive. - The #1 mistake: blocking the file in robots.txt hides the header, so the
noindex is “not found and… therefore ignored.” To deindex: allow crawling +
serve
noindex. - Verify:
curl -Ithe public URL as a fast check, but confirm on a real GET request too (-IsendsHEAD, which can miss GET-only rules); spoof with-A "Googlebot"; watch for CDN-vs-origin drift (the “Noindex detected in X-Robots-Tag” GSC failure). - Bing: supports it too, with
nocache≈noarchive(confirm the live list).
Official documentation
Primary-source documentation for the X-Robots-Tag and the indexing rules it carries.
- Robots meta tag, data-nosnippet, and X-Robots-Tag specifications — the canonical spec: the X-Robots-Tag section, the full directive table, per-crawler targeting, and the crawl-must-be-allowed caveat.
- Block Search Indexing with noindex — the two ways to implement
noindex(meta tag and HTTP header) and the crawlability dependency. - Introduction to robots.txt — what robots.txt does (controls crawling, not indexing) — the other half of why a block hides the header.
Bing / Microsoft
- Robots meta tags and attributes that Bing supports — Bing’s supported directives, including
nocache(≈noarchive). The page is JavaScript-rendered; confirm the exact list in a browser. (URL updated 2026-07-18 — Bing 301-redirected the old slug here.)
Quotes from the source
On-the-record statements from Google’s documentation. Each link is a deep link that jumps to the quoted passage on the source page.
Google — what the X-Robots-Tag is
- “The
X-Robots-Tagcan be used as an element of the HTTP header response for a given URL. Any rule that can be used in a robotsmetatag can also be specified as anX-Robots-Tag.” — Google Search Central docs. Jump to quote
Google — why it exists (non-HTML files)
- “To block indexing of non-HTML resources, such as PDF files, video files, or image files, use the
X-Robots-Tagresponse header instead.” Jump to quote
Google — per-crawler targeting
- “may optionally specify a user agent before the rules” Jump to quote
- “Rules specified without a user agent are valid for all crawlers. The HTTP header, the user agent name, and the specified values are not case sensitive.” Jump to quote
Google — the crawl-must-be-allowed caveat (the spine)
- “…robots meta tags and X-Robots-Tag HTTP headers are discovered when a URL is crawled. If a page is disallowed from crawling through the robots.txt file, then any information about indexing or serving rules will not be found and will therefore be ignored.” Jump to quote
- “For the
noindexrule to be effective, the page or resource must not be blocked by a robots.txt file, and it has to be otherwise accessible to the crawler. If the page is blocked by a robots.txt file or the crawler can’t access the page, the crawler will never see thenoindexrule, and the page can still appear in search results, for example if other pages link to it.” — Google Search Central docs. Jump to quote
Google — two ways to implement noindex
- “There are two ways to implement
noindex: as a<meta>tag and as an HTTP response header.” Jump to quote
nocache ≈ noarchive synonym) is corroborated via secondary coverage — confirm
it against the live page before treating it as final. John Mueller’s commentary on
the robots.txt-block-hides-the-header failure mode, and the “Noindex detected in
X-Robots-Tag” CDN incident class, are paraphrased from industry coverage here, not
quoted, for the same reason — verify exact wording in a browser before quoting. X-Robots-Tag — cheat sheet
Meta tag vs X-Robots-Tag — which to use
| Situation | Use | Why |
|---|---|---|
| HTML page you control the markup of | Robots meta tag | Easiest, per-page, lives in the <head> |
PDF, image, video, feed (no <head>) | X-Robots-Tag header | No HTML to put a meta tag in |
| Whole file type or site-wide rule | X-Robots-Tag header | One server rule covers them all |
| Can’t easily edit each page’s HTML | X-Robots-Tag header | Set it at the server / CDN layer |
The two controls don’t overlap — keep them straight
| Control | Stops crawling? | Stops indexing? | Use it for |
|---|---|---|---|
robots.txt disallow | Yes | No | Keeping bots out of low-value spaces |
X-Robots-Tag: noindex | No (must be crawlable) | Yes | Removing a file from the index |
Block a file in robots.txt and add X-Robots-Tag: noindex and you cancel
yourself out — Google never crawls the file to read the header. Pick one job per
URL.
The “same directives, either delivery method” rule above is Google’s documented contract. It’s a reasonable working assumption for most major crawlers (Bing’s core set overlaps), but it isn’t a guaranteed cross-engine standard — verify directly with any crawler/vendor you specifically depend on.
Per-crawler syntax
| Goal | Header |
|---|---|
| Noindex for everyone | X-Robots-Tag: noindex |
| Noindex for Google only | X-Robots-Tag: googlebot: noindex |
| Different rules per bot | X-Robots-Tag: googlebot: noindexX-Robots-Tag: bingbot: nofollow |
| Timed removal | X-Robots-Tag: unavailable_after: 25 Jun 2010 15:00:00 PST |
| Index only when embedded | X-Robots-Tag: noindex, indexifembedded |
No user-agent token = applies to all crawlers. Header name, user-agent name, and values are all case-insensitive.
Verification, in one line
curl -sI https://example.com/file.pdf | grep -i x-robots-tag- Spoof Googlebot:
curl -A "Googlebot" -sI https://example.com/file.pdf - Always check the public (CDN-fronted) URL, not just origin.
X-Robots-Tag implementation checklist
- Choose the response types and URL patterns that need a header-level directive.
- Keep affected resources crawlable so crawlers can read the header.
- Apply directives at one known layer: origin, application, web server, CDN, or edge.
- Test successful, redirect, error, cached, and uncached responses separately.
- Check crawler-specific prefixes only when a real crawler-specific policy is intended.
- Document ownership and a rollback before applying a broad path or file-type rule.
Playbook: an X-Robots-Tag rollout affects the wrong URLs
- Pause the broad rule or edge deployment.
- Capture headers from affected and unaffected samples, including cache status and redirects.
- Identify the owning layer and exact path, MIME-type, or route match.
- Narrow the condition and remove duplicate directives from other layers.
- Purge relevant caches, then retest the full sample matrix.
- Exit when intended resources carry one coherent policy and ordinary pages do not inherit it.
Common X-Robots-Tag issues
The origin sends the header but the public URL does not
Cause: CDN or proxy behavior strips, caches, or overrides it. Fix: inspect each hop and configure the public edge response as the source of truth.
noindex never takes effect
Cause: robots.txt blocks the resource, so the crawler cannot read its response header. Fix: allow crawling and retain the noindex response.
HTML pages inherit a PDF-only rule
Cause: the server match is too broad or uses the wrong MIME/path condition. Fix: narrow the rule and test multiple file and route types before redeploying.
Patrick's relevant free tools
- Google Index Checker — Check one URL’s observable indexability blockers, or reconcile sitemap, crawl, and supplied Search Console evidence across a URL set before verifying Google’s actual state in URL Inspection.
- Google SERP Simulator — Interactive Google result preview: type a title, description, and URL, compare controlled-font desktop + mobile truncation guidance with simulated query bolding, copy the finished tags, and share a filled-in preview.
- Meta Description Generator — Generate five meta-description options with AI, then compare their measured widths with approximate desktop and mobile SERP-preview guidance. Variants are scored for the keyword, a call to action, and length; you also get a matching title tag and a copy-ready tag block. Quick, paste-content, fetch-URL, and small bulk (≤10) modes. Falls back to editable templates when AI is off.
Tools for header-level robots controls
- HTTP Header Checker — inspect the live public X-Robots-Tag response.
- Robots.txt Tester — confirm the crawler can fetch a resource whose header it must read.
- Redirect Chain Mapper — see which response in a redirect path carries the directive.
- Staging vs. Production SEO Diff — catch environment-specific header drift before release.
Validation tests
Test the live header matrix
Test to run — request representative file types, paths, statuses, and cached/uncached responses with the HTTP Header Checker or curl -I. Expected result — only intended responses carry the exact directive. Failure interpretation — a match rule, cache, or proxy layer is too broad or inconsistent. Monitoring window — immediate. Rollback trigger — revert if indexable HTML or unrelated resources inherit noindex.
Test crawlability plus noindex
Test to run — verify robots access and then fetch the response header as the target crawler. Expected result — crawling is allowed and X-Robots-Tag: noindex is visible. Failure interpretation — robots rules or crawler-specific header syntax prevents the policy from being read. Monitoring window — immediate technically; index removal waits for recrawl. Rollback trigger — restore access immediately if a broad robots change blocks required resources.
Test yourself: X-Robots-Tag
Server config to noindex PDFs
These are known-good config patterns I’d reach for — solid starting points, but
confirm them against your own stack (and the live curl -I check at the bottom)
before relying on them. They are not Google quotes.
Apache (.htaccess or vhost — needs mod_headers)
Noindex every PDF:
<FilesMatch "\.pdf$">
Header set X-Robots-Tag "noindex, nofollow"
</FilesMatch>Multiple file types at once:
<FilesMatch "\.(pdf|docx?|xlsx?|pptx?)$">
Header set X-Robots-Tag "noindex, noarchive, nosnippet"
</FilesMatch> Notes: Apache needs mod_headers enabled. Header set overwrites any existing
value — use Header append if another rule may already set the header. To target
one crawler, put the token in the value: Header set X-Robots-Tag "googlebot: noindex".
Nginx (inside a server {} or location block)
Noindex every PDF:
location ~* \.pdf$ {
add_header X-Robots-Tag "noindex, nofollow";
}Multiple types:
location ~* \.(pdf|docx?|xlsx?|pptx?)$ {
add_header X-Robots-Tag "noindex, noarchive, nosnippet";
}Notes: the directive has to live in an active server/location block, and Nginx
needs a reload (nginx -s reload) to pick it up. Inheritance trap: Nginx only
inherits add_header directives from a parent block (server {}) into a child
block (location {}) when the child has no add_header of its own. The
moment a location block adds any header — even an unrelated one, like a CORS or
cache-control header — it silently stops inheriting every add_header set above
it, including your X-Robots-Tag. If that happens, repeat the X-Robots-Tag
line inside the child block; don’t assume it carried over.
Cloudflare — two options
Option 1 — Transform Rule (no code). Rules → Transform Rules → Modify Response
Header → set X-Robots-Tag = noindex, nofollow when
http.request.uri.path ends with .pdf.
Option 2 — Worker on a route matching *.pdf:
export default {
async fetch(request, env, ctx) {
const res = await fetch(request);
const out = new Response(res.body, res);
out.headers.set("X-Robots-Tag", "noindex, nofollow");
return out;
}
};Either way, a CDN sitting in front of your origin can add, strip, or cache this header — which is exactly why you verify against the public URL below, not origin.
Verify the live header with curl
curl -I prints the response headers without downloading the body. Check the
public URL (the one Google fetches), and optionally spoof the bot view.
macOS / Linux
# Print all response headers
curl -I https://example.com/file.pdf
# Just the X-Robots-Tag line
curl -sI https://example.com/file.pdf | grep -i x-robots-tag
# See what Googlebot would receive (spoof the user agent)
curl -A "Googlebot" -sI https://example.com/file.pdf | grep -i x-robots-tag
# Confirm on a real GET request too — -I sends HEAD, and a rule scoped to
# GET-only responses won't show up in a HEAD check
curl -sD - -o /dev/null https://example.com/file.pdf | grep -i x-robots-tagWindows (PowerShell)
# Inspect the response headers
(Invoke-WebRequest -Method Head -Uri "https://example.com/file.pdf").Headers["X-Robots-Tag"]
# Spoof the Googlebot user agent
(Invoke-WebRequest -Method Head -Uri "https://example.com/file.pdf" `
-UserAgent "Googlebot").Headers["X-Robots-Tag"]If the header is missing, the most common causes are: it’s set on origin but
stripped/overridden at the CDN; mod_headers isn’t enabled (Apache); the config
wasn’t reloaded (Nginx); an Nginx location block redefined add_header and
silently stopped inheriting the parent’s X-Robots-Tag line; the rule only
fires on GET and you tested with -I (HEAD); or the file is blocked in
robots.txt, so Google never fetches it to see the header in the first place.
X-Robots-Tag
The X-Robots-Tag is an HTTP response header that carries the same indexing and serving directives as the robots meta tag (noindex, nofollow, nosnippet, and the rest). Because it lives in the header rather than the HTML, it's how you control indexing for non-HTML files like PDFs, images, and videos.
Related: Robots Meta Tag, Noindex, nosnippet & data-nosnippet
X-Robots-Tag
The X-Robots-Tag is an HTTP response header that carries the same indexing and serving directives as the robots <meta> tag — noindex, nofollow, nosnippet, noarchive, max-snippet, max-image-preview, max-video-preview, unavailable_after, noimageindex, indexifembedded, notranslate, none, and all. Anything you can put in a robots meta tag, you can send as an X-Robots-Tag header instead — that equivalence is Google’s documented contract; Google itself notes other search engines may not treat the rules the same way. You can also combine multiple directives in a comma-separated list or repeated header lines; Google resolves conflicting rules by applying the more restrictive one.
The reason it exists is simple: non-HTML files have no <head> to drop a meta tag into. A PDF, an image, or a video can’t carry a robots meta tag, so when you need to noindex one of those, the header is the supported route. Because it’s set at the server level (Apache, Nginx, or a CDN like Cloudflare), a single rule can apply a directive to a whole class of files — every .pdf on the site, say — or even site-wide. You can optionally target one crawler by prefixing the directive with a user-agent token, e.g. X-Robots-Tag: googlebot: noindex; with no token, the rule applies to every crawler.
It shares one hard caveat with the meta tag: the URL has to be crawlable. If you block the file in robots.txt, Google never fetches it, never sees the header, and the noindex is silently ignored. So the header controls indexing, not crawling — crawling is robots.txt’s job, and the two have to cooperate. Verify a live header with curl -I against the public URL, and watch for a CDN serving a different header than your origin.
Related: Robots Meta Tag, Noindex, nosnippet & data-nosnippet
Build-time retrieval analysis plus live signals for this exact article. The automatic chunk report includes a deterministic readiness score and is ready without a model download.
Search Console
sampleGA4 traffic (28d)
sampleCloudflare traffic (7d)
sampledCrUX field data (28d, phone)
sampleGoogle NLP entities
localChangelog
Updated Jul 18, 2026.
Editorial summary and recorded change details.Summary
Scoped the meta-tag/X-Robots-Tag directive equivalence to Google specifically (Google's own doc notes other search engines may not treat the rules the same way), added Google's documented multiple-rules/conflict-resolution behavior, tightened server-config and curl verification guidance (Nginx add_header inheritance trap, GET vs HEAD), and added a worked non-HTML noindex example.
Change details
-
Added a new 'Multiple rules and conflicting directives' section covering comma-separated/repeated X-Robots-Tag headers and Google's more-restrictive-rule-wins conflict resolution, sourced from a fresh re-fetch of Google's robots-meta-tag doc.
-
Scoped the 'same directives as the meta tag' equivalence explicitly to Google in the Advanced lens, cheat-sheet, and glossary, quoting Google's own caveat that other search engines may not treat the rules the same way.
-
Documented the Nginx add_header non-inheritance trap (a child location block that sets its own add_header stops inheriting the parent's X-Robots-Tag) in the Scripts lens and troubleshooting causes.
-
Added a GET-vs-HEAD caveat to curl verification guidance in both the Advanced and Scripts lenses, since curl -I sends HEAD and can miss GET-only header rules.
-
Added a concrete PDF noindex worked example stating the fetchability requirement inline, and updated the Bing citation URL to the page's current 301 target.
Full comparison unavailable — no prior snapshot was archived for this revision.