Robots.txt

What robots.txt actually does — it controls crawling, not indexing — plus the exact syntax, how Google handles it under the hood, and the mistakes that break sites.

First published: Jun 23, 2026 · Last updated: Jul 30, 2026 · Advanced
demand #3 in Crawling#6 in How Search Works#23 in Technical SEO#31 on the site
1 evidence signal on this page

Robots.txt is a plain-text file at the root of each host that tells crawlers which URLs they may and may not request. The one thing to get right: it controls crawling, not indexing. A disallowed URL can still be indexed without a snippet if it's linked from elsewhere — to keep a page out of the index you use noindex, and the page must NOT be blocked in robots.txt or Google never sees the noindex. Google supports only user-agent, allow, disallow, and sitemap (noindex, nofollow, and crawl-delay were dropped Sept 1, 2019). It lives at /robots.txt, is scoped to one host+protocol+port, caps at 500 KiB, caches ~24h, and a 4xx means no restrictions while a 5xx can stall crawling site-wide. Don't block render-critical CSS/JS, and don't rely on it to hide anything — the file is public.

TL;DR — Robots.txt is a plain-text file at the root of each host (/robots.txt, lowercase) that implements the Robots Exclusion Protocol (RFC 9309). It controls crawling, not indexing — a disallowed URL can still be indexed without a snippet if linked elsewhere; to deindex use noindex on a page that is not blocked. Google supports only user-agent, allow, disallow, and sitemap; noindex/nofollow/crawl-delay were dropped Sept 1, 2019. Scope is one host+protocol+port. Matching uses the most-specific (longest) rule, least-restrictive on ties; * and $ are the wildcards; paths are case-sensitive. Google caps the file at 500 KiB, caches ~24h, treats 4xx (except 429) as no-restrictions, and on a 5xx stalls crawling for ~12h then falls back to the last good copy for ~30 days. Don’t block render-critical CSS/JS, and don’t treat it as access control — the file is public.

What it is and where it lives

Robots.txt implements the Robots Exclusion Protocol, created by Martijn Koster in 1994 and finally standardized in 2022 as RFC 9309 — co-authored by Google’s Gary Illyes, Henner Zeller, Lizzi Sassman, and Koster himself. The standard’s own wording: “This document specifies and extends the ‘Robots Exclusion Protocol’ method originally defined by Martijn Koster in 1994 for service owners to control how content served by their services may be accessed, if at all, by automatic clients known as crawlers.”

A few facts that catch people out:

  • It must be at the root, lowercase. RFC 9309 is explicit: “The rules MUST be accessible in a file named ‘/robots.txt’ (all lowercase) in the top-level path of the service.” Google adds that the URL itself is case-sensitive, like any URL.
  • Scope is one host + protocol + port. Google: “The rules listed in the robots.txt file apply only to the host, protocol, and port number where the robots.txt file is hosted.” So https://example.com, https://www.example.com, https://blog.example.com, and http://example.com each need their own file. Subdomains and protocols don’t share one.
  • Supported protocols for Google are HTTP, HTTPS, and FTP.

The misconception that defines this topic: crawling vs indexing

If you take one thing from this page, take this: robots.txt controls crawling, not indexing. Blocking a URL is not the same as removing it from Google. Evidence for this claim A robots.txt rule controls crawling rather than guaranteeing removal from Google Search; a URL can still appear when Google cannot crawl it. Scope: Google Search crawler behavior. Other crawlers can interpret robots.txt differently. Confidence: high · Verified: Google: Introduction to robots.txt

Google’s own intro doc says it plainly: robots.txt “is not a mechanism for keeping a web page out of Google. To keep a web page out of Google, block indexing with noindex or password-protect the page.” And on what actually happens to a blocked URL: “While Google won’t crawl or index the content blocked by a robots.txt file, we might still find and index a disallowed URL if it is linked from other places on the web.” The result is the familiar snippet-less listing: “its URL can still appear in search results, but the search result won’t have a description.”

Evidence for this claim Robots.txt controls crawler access, not index eligibility; Google may still index a disallowed URL discovered through links, typically without a content snippet. Scope: web crawling Confidence: high · Verified: Robots.txt Introduction and Guide

The spec restates the same nuance for the disallow rule itself: “Google can’t index the content of pages which are disallowed for crawling, but it may still index the URL and show it in search results without a snippet.”

Why you must NOT block a page you want to noindex

This is the trap that quietly breaks deindexing efforts. A noindex only works if Google can crawl the page to read it. Google’s block-indexing doc spells out the dependency: “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, for example if other pages link to it.” Evidence for this claim Google must be able to crawl a URL to see a noindex rule; blocking the URL in robots.txt can prevent the rule from being observed. Scope: Google Search indexing controls for HTML meta robots and X-Robots-Tag rules. Confidence: high · Verified: Google: Block indexing with noindex

So if your goal is to get a page out of the index, John Mueller’s guidance is the cleanest way to remember it: when you want to unindex pages, you should not block Google with robots.txt, but rather use noindex.

The lived proof: I blocked two of our own high-ranking pages

I don’t have to argue this from theory. In my experiment blocking two high-ranking Ahrefs pages, I deliberately blocked them in robots.txt and tracked what happened. The pages stayed indexed and kept ranking — they didn’t vanish. What we lost was the freshness Google gets from re-crawling: “We lost a position here or there and all of the featured snippets for the pages.” Traffic dropped, but less than I expected: “Both pages lost some traffic. But it didn’t result in much change to our traffic estimate like I was expecting.”

My takeaway from the data: “Accidentally blocking pages (that Google already ranks) from being crawled using robots.txt probably isn’t going to have much impact on your rankings, and they will likely still show in the search results.” And the blunt version: “Don’t block pages you want indexed. It hurts. Not as bad as you might think it does—but it still hurts.”

The flip side is reassurance: when Search Console flags “Indexed, though blocked by robots.txt” for a utility URL — cart, filter, parameter junk — it’s usually a non-issue. As Mueller put it about add-to-cart URLs, blocking them is fine, and even if they get “indexed,” it’s unlikely they’ll be shown in search unless someone runs a very specific query for those URLs, which real users don’t do. Distinguish the scary-sounding warning from an actual problem: it only matters if the blocked URL is a page you actually wanted crawled and indexed.

The syntax (the reference)

A robots.txt is a set of groups. Each group starts with one or more User-agent lines naming which crawler(s) it applies to, followed by the rules for them.

User-agent: *
Disallow: /cart/
Disallow: /search
Allow: /search/help

User-agent: Googlebot
Disallow: /no-google/

Sitemap: https://example.com/sitemap.xml

User-agent and groups. A crawler obeys exactly one group — the one with the most specific user-agent that matches it — and ignores the rest. Google: “Google’s crawlers determine the correct group of rules by finding in the robots.txt file the group with the most specific user agent that matches the crawler’s user agent. Other groups are ignored.” And: “Only one group is valid for a particular crawler.” (Bing behaves the same way — more on that below.)

That also means a specific group doesn’t get topped up with the wildcard group’s rules — it’s used on its own, not merged with User-agent: *. Google’s spec is explicit that “user agent specific groups and global groups (*) are not combined.” So if you write a User-agent: googlebot-news group, it has to be self-contained: anything you still want it to obey from the * group has to be repeated inside it, or Googlebot-News simply won’t see those rules at all.

Evidence for this claim For Google's crawlers, the most specific matching user-agent group applies; rules from that specific group are not combined with the global asterisk group, although multiple matching specific groups are merged internally. Scope: robots.txt parsing and fetching Confidence: high · Verified: How Google Interprets the robots.txt Specification

Disallow and Allow. Disallow lists paths a crawler must not request; Allow carves exceptions back out. The disallow rule “specifies paths that must not be accessed by the crawlers identified by the user-agent line the disallow rule is grouped with.” The allow rule “specifies paths that may be accessed by the designated crawlers. When no path is specified, the rule is ignored.”

The matching rule (most guides get this wrong). When two rules conflict, the most specific one wins, and “most specific” means longest path: “When matching robots.txt rules to URLs, crawlers use the most specific rule based on the length of the rule path. In case of conflicting rules, including those with wildcards, Google uses the least restrictive rule.” So on a genuine tie, the least restrictive rule wins — Allow beats Disallow. RFC 9309 frames it as the “Longest Match”: “The following example shows that in the case of two rules, the longest one is used for matching.” Evidence for this claim Google resolves matching robots.txt rules by path specificity and uses the least restrictive rule when equally specific rules conflict. Scope: Google crawler interpretation of robots.txt rules; other crawlers may implement different extensions. Confidence: high · Verified: Google: Robots.txt interpretation

Worked example:

User-agent: *
Allow: /folder/page
Disallow: /folder/

The URL /folder/page matches both rules. Allow: /folder/page (12 chars) is longer than Disallow: /folder/ (8 chars), so the longer, more specific Allow wins and the page is crawlable.

Wildcards * and $. Google: * designates 0 or more instances of any valid character. $ designates the end of the URL.” So Disallow: /*.pdf$ blocks every URL ending in .pdf, and Disallow: /*? blocks every URL containing a query string. Matching is prefix-based: Disallow: /fish matches /fish, /fish.html, and /fish/salmon.html, but not /Fish (case-sensitive) or /catfish (it’s a prefix, not a substring).

Case sensitivity (the subtle one). Field and user-agent names are case-insensitive; path values are case-sensitive. Google: “Both the user-agent field name and its value are case-insensitive,” but “The field name (disallow) is case-insensitive, but its value is case-sensitive,” and “The path value must start with / to designate the root and the value is case-sensitive.” So Disallow: /Folder/ does not block /folder/.

Sitemap. The Sitemap: directive takes a full absolute URL and is independent of groups — it can sit anywhere in the file.

Comments. Anything after # is ignored: “To include comments, precede your comment with the # character.”

noindex, nofollow, and crawl-delay are NOT robots.txt directives

This is a persistent myth. As of September 1, 2019, Google retired support for unsupported, undocumented rules — including noindex, nofollow, and crawl-delay. Google’s announcement focused on rules unsupported by the internet draft, such as crawl-delay, nofollow, and noindex, noting they were never documented by Google, and said Google was retiring all code that handles unsupported and unpublished rules (such as noindex) on that date. The supported field list is short, and the spec calls out the exclusion directly: Google supports user-agent, allow, disallow, and sitemap, and “other fields such as crawl-delay aren’t supported.”

If you relied on noindex in robots.txt, the alternatives are a noindex meta tag or X-Robots-Tag header, 404/410 status codes, password protection, a Disallow, or the Search Console removal tool.

How Google handles robots.txt under the hood

  • Size limit: 500 KiB. “Google enforces a robots.txt file size limit of 500 kibibytes (KiB). Content which is after the maximum file size is ignored.” RFC 9309 aligns: “The parsing limit MUST be at least 500 kibibytes [KiB].”
  • Caching: ~24 hours. “Google generally caches the contents of robots.txt file for up to 24 hours, but may cache it longer in situations where refreshing the cached version isn’t possible.” So a change isn’t necessarily picked up instantly. Evidence for this claim Google generally caches robots.txt for up to 24 hours and changes crawling behavior according to the HTTP status returned for the file. Scope: Google crawler handling of robots.txt fetches, including documented 4xx, 5xx, and redirect behavior. Confidence: high · Verified: Google: Robots.txt file handling
  • Status codes matter site-wide. This is the part most guides skip:
    • 4xx (except 429) → no restrictions. “Google’s crawlers treat all 4xx errors, except 429, as if a valid robots.txt file didn’t exist. This means that Google assumes that there are no crawl restrictions.” A 404 on /robots.txt means “crawl everything.” (Don’t use 401/403 to throttle crawling.)
    • 5xx / unreachable → dangerous. “For the first 12 hours, Google stops crawling the site but keeps trying to fetch the robots.txt file. If Google can’t fetch a new version, for the next 30 days Google will use the last good version, while still trying to fetch a new version.” So a server error on /robots.txt can effectively disallow your whole site for the first ~12 hours, then run on the last cached copy for ~30 days. A persistently erroring robots.txt is a site-wide crawl risk. And if it’s still broken after those 30 days: “If the errors are still not fixed after 30 days: If the site is generally available to Google, Google will behave as if there is no robots.txt file (but still keep checking for a new version).” In other words, a robots.txt that never recovers doesn’t stay disallowed forever — Google eventually falls back to crawling with no restrictions, the same as a 404.
    • 3xx → Google follows at least five redirect hops, then treats it as a 404.

robots.txt in Bing, Yandex, and beyond

The grouping and syntax are essentially shared, but two divergences matter:

  • crawl-delay. Google ignores it, Bing still honors it, and Yandex dropped it in 2018 — Yandex’s own documentation states that “From February 22, 2018, Yandex doesn’t take into account the Crawl-delay directive,” pointing you to the site crawl rate setting in Yandex Webmaster instead. Bing is explicit that “The robots.txt file is the only valid place to set a crawl-delay directive for MSNBot,” and that the directive “accepts only positive, whole numbers as values… the higher the value, the more throttled down the crawl rate will be.” Note Bing treats the value as a relative throttle, not literally N seconds.
  • The bingbot-section gotcha. Just like Google’s “only one group per crawler” rule, if you create a User-agent: bingbot section, Bing applies only that section and ignores the User-agent: * defaults (crawl-delay excepted). So a bingbot-specific group must repeat every directive you still want enforced.
  • Amazon’s cache and failure behavior. Amazon says its crawlers may use a robots.txt copy cached within the previous 30 days. If they cannot fetch the file, they behave as though it does not exist. A checker can report the copy it fetched, but it cannot prove which cached version Amazon used—or that Amazon observed the same failure as the checker. Evidence for this claim Amazon says its crawlers may use a robots.txt copy cached within the previous 30 days and behave as though the file does not exist when they cannot fetch it. Scope: Amazon crawler behavior only; a checker result cannot establish which cached copy Amazon used or whether Amazon observed the same fetch failure. Confidence: high · Verified: Amazon: Amazonbot

Managing AI crawlers with robots.txt

Robots.txt is currently the main lever for managing AI crawlers, and they obey the same group/user-agent syntax. The catch: these are separate tokens, so blocking one doesn’t block the others.

  • OpenAI runs several distinct bots, and the controls for each are independent — allowing one doesn’t allow the others, and blocking one doesn’t block the others. GPTBot crawls content for training OpenAI’s models; OAI-SearchBot surfaces sites in ChatGPT’s search features; OAI-AdsBot checks the safety of pages submitted as ads (its data isn’t used for training). Block training with User-agent: GPTBot / Disallow: / — that alone won’t stop the search or ads bots. ChatGPT-User is different again: it fires for actions a person triggers inside ChatGPT or a Custom GPT, not automatic crawling, and OpenAI says “robots.txt rules may not apply” to it — so don’t count on a Disallow to keep it out. If you do change what OAI-SearchBot can crawl, OpenAI notes it can take about 24 hours for the update to reach their search systems.
  • Google-Extended controls Gemini/Vertex training and is separate from Googlebot.
  • Others worth naming: CCBot (Common Crawl), ClaudeBot (Anthropic), PerplexityBot, and Bytespider.

The hard caveat: compliance is voluntary. Robots.txt requests; it doesn’t enforce. Well-behaved crawlers obey it; scrapers can and do ignore it. If you truly need to keep something away from a bot, that’s an authentication/blocking problem, not a robots.txt one.

Common mistakes (and the fixes)

The file is 200, but it is not actually a usable robots file. Status alone is not enough. Capture the response Content-Type and first bytes: a CDN/custom-error template can return HTML at /robots.txt with 200, which must be a warning rather than an “allow all” pass. Google documents robots.txt as UTF-8 plain text and may ignore invalid characters. A single UTF-8 BOM at the beginning is tolerated, but a second BOM, a BOM in the middle, UTF-16 bytes, NULs, or invisible/control characters can alter the first token or invalidate a line. Show the byte offset and affected line; do not silently normalize the file before telling the user what the crawler received. Apply Google’s effective 500 KiB parsing limit before calculating allow/disallow results, while still reporting the discarded tail.

  • Blocking a page you also want deindexed. Block + noindex means Google never crawls it to see the noindex. Use noindex without the block.
  • Using robots.txt to deindex. Wrong tool entirely — that’s noindex’s job.
  • Blocking render-critical CSS/JS. Google needs those assets to see the page as a user does; Google’s own sample robots.txt explicitly re-allows .css/.js so Googlebot can crawl them.
  • Trying to hide sensitive data. RFC 9309 is blunt: “The Robots Exclusion Protocol is not a substitute for valid content security measures. Listing paths in the robots.txt file exposes them publicly and thus makes the paths discoverable.” Disallowing /secret-admin/ literally advertises it. Use auth.
  • A stray Disallow: /. This blocks the entire site for the named crawler — the classic staging leftover that takes a site out of Google.
  • Ignoring the response code on /robots.txt. A 5xx can stall crawling site-wide; treat the file’s availability as production-critical.

For the broader pipeline this sits inside — discovery, the crawl scheduler, rendering, and how crawling differs from indexing — see the crawling hub. The sibling topics (crawl budget, and how Google handles sitemaps) each go deeper on one piece of this.

Who's been ignoring my robots.txt?

This is live data from this site, not an illustration. My robots.txt disallows /api/trap/ and the only link to it is invisible to humans — so a compliant crawler will never request it. Every user-agent below fetched it anyway. (Humans poking at it with curl show up too; the user-agent usually gives them away.)

Loading trap log…

Add an expert note

Pin an expert quote

New person? Create their unclaimed profile at /admin/experts/ → Pin an expert quote first.