# InsiderAlpha robots.txt
# Allow major search engines to crawl public marketing/content pages.
# Disallow personal/authenticated app surfaces and API endpoints.
#
# Editing this file? Copy it byte for byte to edge/robots-fallback.txt in the
# same commit. The edge router serves that copy whenever this server cannot
# answer, because Google reads a 5xx on robots.txt as "stop crawling the whole
# site" for about 12 hours. public-frontend/tests/edgeRobotsFallback.test.ts
# fails while the two files differ.
User-agent: *
Allow: /
# Authenticated personal areas (no value to search index)
Disallow: /my-trades
Disallow: /performance
Disallow: /portfolio
Disallow: /settings
Disallow: /profile
Disallow: /brokers
Disallow: /trading-plan
Disallow: /trade-picker
Disallow: /mcp
# /subscription-required and the other auth-adjacent PAGES are intentionally
# NOT disallowed here: they serve , and
# Google must be allowed to CRAWL a URL to SEE its noindex and drop it from
# the index. A robots.txt Disallow would hide the noindex and let bare URLs
# linger indexed.
#
# /login is the exception, and is disallowed (2026-08-31). Until 2026-10-10 it
# was not a page: outside the rare Auth0-error case it answered a 307 into
# /auth/login, the same character as the /auth/ endpoints below. It is now
# the sign-in chooser, noindex like /register, and stays disallowed for the
# reasons that follow, which have not changed. The header links /login on every page, and
# between 2026-08-27 and 2026-09-16 the signed-out asks on every insider page
# also minted a UNIQUE /login?returnTo={path}, one redirecting URL per
# document: Ahrefs' 2026-08-30 crawl flagged 1,438 pages "links to redirect"
# for them and Search Console's "Blocked by robots.txt" bucket reached 41,601
# URLs. From the deploy of the 2026-09-16 change on, no document carries such
# a link: a destination that names the page is attached when the reader
# clicks and is never rendered as
# an href (public-frontend/components/AccountLink.tsx). This rule stays for
# the header link and for the minted URLs Google already holds; it keeps
# listing them until it recrawls their sources. Never press Validate Fix on
# that bucket, it fails by design while these Disallows exist:
# docs/seo/SEARCH_CONSOLE_ROBOTS_BUCKET.md.
Disallow: /login
# Cloudflare's infrastructure path. Email Address Obfuscation rewrites the
# footer's mailto into /cdn-cgi/l/email-protection#..., which answers 404 when
# fetched as a document; Cloudflare's own guidance is to disallow /cdn-cgi/ so
# crawlers do not report it as a sitewide broken link.
Disallow: /cdn-cgi/
# Backend API: no SEO value, can be expensive to crawl
Disallow: /api/
# The one API document that IS meant to be read by a machine on a reader's
# behalf. /api/pricing is anonymous JSON carrying only the public price
# ladder, the same figures /pricing renders, and llms.txt and llms-full.txt
# both send assistants there for the live prices. Longest match wins, so this
# reopens exactly that path and nothing else under /api/. The rule is repeated
# in every AI stanza below, because each of those groups is read on its own.
Allow: /api/pricing
# The Next server-side data proxy. Same character as /api/ - it returns JSON
# for the authenticated app, never a document.
Disallow: /bff/
# OAuth handshake endpoints. Unlike the SPA auth PAGES above, these are pure
# redirects with no body, so there is no noindex for a crawler to discover and
# nothing to keep out of the index; the only effect of crawling them is wasted
# budget bouncing off the identity provider.
Disallow: /auth/
# /share/* is a backend-owned path that no longer backs any page on this site.
# Nothing in public-frontend/ calls it: Next reaches the backend over the Swarm
# network via BACKEND_URL, never over this public path. Two things still live
# there, both driven from outside the frontend: /share/{ticker}, which is now a
# permanent 301 to /company/{ticker} kept alive for alert links frozen in
# Discord channel history, and /share/insider/{slug}, the last server-rendered
# page in the stack. It stays disallowed because the canonical URLs are
# /company/{ticker}, /insider/{name-slug}-{id} and /learn/{slug}, and indexing
# the raw source of those pages would be duplicate content. The insider shape
# is the whole slug, not the bare id: /insider/{id} answers a 301 to it, so a
# comment naming the short form describes a redirect rather than a canonical.
Disallow: /share/
# PostHog reverse-proxy paths — analytics endpoints, not page content. Bots
# that render JS (meta-externalagent, etc.) hammer these for no SEO value.
Disallow: /panda/
# Next.js React Server Component payloads. The app router fetches the next
# page's data as /{path}?_rsc={hash}, with an `RSC: 1` request header, when a
# visitor hovers or is about to click a link. A crawler that finds those URLs
# in a rendered page and fetches them WITHOUT the header gets the ordinary HTML
# document back: one more copy of a page it already has, under a URL that
# differs only by a cache-busting hash. Measured 2026-10-12: 96% of
# OAI-SearchBot's fetches were ?_rsc= variants. Nothing a crawler needs lives
# behind the query: Google's renderer reads the page HTML and follows ,
# never the prefetch, and a browser is not a robot and is unaffected. `*` is
# the wildcard Google, Bing and the AI fetchers all document, so this closes
# the variant on every path at once. Repeated in each AI stanza below, because
# a crawler reads only its own group.
Disallow: /*?_rsc=
# Facebook / Meta external agent: extremely heavy crawler that fully renders
# the SPA (includes PostHog flag/config requests). Provides no SEO value to
# our product and accounted for ~50% of bot traffic in May 2026. Restrict to
# the OG share surface only.
#
# The two template sets are named explicitly even though `Disallow: /` already
# covers them. Longest match wins, so if anyone ever softens the default here
# the way `facebookexternalhit` below had been softened, /insider/ and
# /company/ stay closed instead of quietly reopening the 53,000 URLs this
# stanza exists to keep Meta off.
User-agent: meta-externalagent
Disallow: /
Disallow: /insider/
Disallow: /company/
Allow: /share/
Allow: /og-image.png
Allow: /favicon.ico
Allow: /favicon.svg
User-agent: meta-externalfetcher
Disallow: /
Disallow: /insider/
Disallow: /company/
Allow: /share/
Allow: /og-image.png
Allow: /favicon.ico
Allow: /favicon.svg
# meta-webindexer is the newest name in the same Meta crawl fleet (2026-10-12:
# 28.7% of origin traffic, and it had never once fetched this file, so it was
# crawling under no rules at all). Same job as the two stanzas above, so the
# same rules: off the two heavy templates, the OG share surface open. Like
# them, this is intent; the enforcing layer is the Cloudflare rate-limit rule
# on AS32934.
User-agent: meta-webindexer
Disallow: /
Disallow: /insider/
Disallow: /company/
Allow: /share/
Allow: /og-image.png
Allow: /favicon.ico
Allow: /favicon.svg
# facebookexternalhit is Meta's LINK-PREVIEW fetcher, and it is deliberately
# NOT treated like the two stanzas above. It is not part of a crawl: it makes
# one request, when a PERSON pastes an InsiderAlpha URL into WhatsApp,
# Messenger or a Facebook post, so the chat renders a title, a description and
# a card instead of a naked link. The crawl fleet sweeps URLs nobody asked
# for; this fetcher only ever asks for a page someone already chose to share.
#
# It was briefly given Disallow: /company/, /insider/ and /share/ on
# 2026-08-29 on the theory that it was the same fleet. It is not, and that
# bought nothing. The sweep that pushed the origin over was
# meta-externalagent plus raw AS32934 address ranges (measured 2026-08-29:
# 45/45 clean responses at concurrency 3 against 41.7% 5xx at concurrency 8,
# with the database pool logging 30/30 connections checked out in the same
# window), robots.txt is ADVISORY in any case, and the layer that enforces
# the limit is a Cloudflare rate-limit rule on AS32934 that lives in the
# dashboard and not in this repository. What the change did cost was the
# preview on every shared company and insider link.
#
# So: documents open, endpoints closed. The Disallows below are endpoints and
# not pages, and nothing an unfurler does needs the JSON API, the server-side
# data proxy, the OAuth redirects or the analytics proxy.
#
# /share/ is open HERE and nowhere else among the Meta stanzas' siblings.
# /share/{ticker} is a 301 into /company/{ticker} kept alive for alert links
# frozen in Discord channel history and /share/insider/{slug} is the last
# server-rendered page in the stack, so /share/ is the surface built for
# exactly this fetcher. It stays shut to indexers because it is duplicate
# content, and a preview fetcher indexes nothing.
#
# The four Allow lines are redundant against `Allow: /` and are here on
# purpose. Longest match wins and a tie goes to Allow, so a later
# "consistency fix" that pastes the crawl fleet's Disallows into this stanza
# cannot quietly take the previews down a second time. If you arrived here
# wanting to close these paths, the thing you actually want is the WAF rule.
User-agent: facebookexternalhit
Allow: /
Allow: /company/
Allow: /insider/
Allow: /learn/
Allow: /share/
Disallow: /api/
Disallow: /bff/
Disallow: /auth/
Disallow: /panda/
Disallow: /login
Disallow: /cdn-cgi/
# FacebookBot is Meta's bulk crawler for AI training, NOT the link-preview
# fetcher above; this comment used to call it "link-preview / AI-training",
# and that conflation is how the preview fetcher ended up with a crawler's
# rules. It is therefore treated as what it is, and identically to every
# other AI crawler in this file (GPTBot, ClaudeBot, CCBot and the rest):
# public content open, /share/ closed as duplicate content, endpoints closed.
# It has never appeared in the load forensics, and shutting one more AI
# crawler out of the templates would be the withholding lever the rest of
# this file exists to warn about. Revisit only if the traffic actually moves
# here, and revisit it in the WAF first.
User-agent: FacebookBot
Allow: /
Disallow: /api/
Allow: /api/pricing
Disallow: /bff/
Disallow: /auth/
Disallow: /share/
Disallow: /panda/
Disallow: /login
Disallow: /cdn-cgi/
Disallow: /*?_rsc=
# ---------------------------------------------------------------------------
# AI crawlers (LLM training + answer-engine bots).
# Explicit allow-rules so they index public content but stay off /api/, /share/
# (canonical URL is /company/*, /insider/* etc.) and analytics endpoints.
# ---------------------------------------------------------------------------
User-agent: GPTBot
Allow: /
Disallow: /api/
Allow: /api/pricing
Disallow: /bff/
Disallow: /auth/
Disallow: /share/
Disallow: /panda/
Disallow: /login
Disallow: /cdn-cgi/
Disallow: /*?_rsc=
User-agent: ChatGPT-User
Allow: /
Disallow: /api/
Allow: /api/pricing
Disallow: /bff/
Disallow: /auth/
Disallow: /share/
Disallow: /panda/
Disallow: /login
Disallow: /cdn-cgi/
Disallow: /*?_rsc=
User-agent: OAI-SearchBot
Allow: /
Disallow: /api/
Allow: /api/pricing
Disallow: /bff/
Disallow: /auth/
Disallow: /share/
Disallow: /panda/
Disallow: /login
Disallow: /cdn-cgi/
Disallow: /*?_rsc=
User-agent: ClaudeBot
Allow: /
Disallow: /api/
Allow: /api/pricing
Disallow: /bff/
Disallow: /auth/
Disallow: /share/
Disallow: /panda/
Disallow: /login
Disallow: /cdn-cgi/
Disallow: /*?_rsc=
User-agent: anthropic-ai
Allow: /
Disallow: /api/
Allow: /api/pricing
Disallow: /bff/
Disallow: /auth/
Disallow: /share/
Disallow: /panda/
Disallow: /login
Disallow: /cdn-cgi/
Disallow: /*?_rsc=
User-agent: PerplexityBot
Allow: /
Disallow: /api/
Allow: /api/pricing
Disallow: /bff/
Disallow: /auth/
Disallow: /share/
Disallow: /panda/
Disallow: /login
Disallow: /cdn-cgi/
Disallow: /*?_rsc=
User-agent: Perplexity-User
Allow: /
Disallow: /api/
Allow: /api/pricing
Disallow: /bff/
Disallow: /auth/
Disallow: /share/
Disallow: /panda/
Disallow: /login
Disallow: /cdn-cgi/
Disallow: /*?_rsc=
User-agent: Google-Extended
Allow: /
Disallow: /api/
Allow: /api/pricing
Disallow: /bff/
Disallow: /auth/
Disallow: /share/
Disallow: /panda/
Disallow: /login
Disallow: /cdn-cgi/
Disallow: /*?_rsc=
User-agent: Applebot-Extended
Allow: /
Disallow: /api/
Allow: /api/pricing
Disallow: /bff/
Disallow: /auth/
Disallow: /share/
Disallow: /panda/
Disallow: /login
Disallow: /cdn-cgi/
Disallow: /*?_rsc=
User-agent: Amazonbot
Allow: /
Disallow: /api/
Allow: /api/pricing
Disallow: /bff/
Disallow: /auth/
Disallow: /share/
Disallow: /panda/
Disallow: /login
Disallow: /cdn-cgi/
Disallow: /*?_rsc=
User-agent: Bytespider
Allow: /
Disallow: /api/
Allow: /api/pricing
Disallow: /bff/
Disallow: /auth/
Disallow: /share/
Disallow: /panda/
Disallow: /login
Disallow: /cdn-cgi/
Disallow: /*?_rsc=
User-agent: CCBot
Allow: /
Disallow: /api/
Allow: /api/pricing
Disallow: /bff/
Disallow: /auth/
Disallow: /share/
Disallow: /panda/
Disallow: /login
Disallow: /cdn-cgi/
Disallow: /*?_rsc=
# Answer-engine fetchers added 2026-10-12. Each is the user-triggered or
# search-index half of a vendor whose training crawler already has a stanza
# above (Claude-User and Claude-SearchBot beside ClaudeBot, MistralAI-User for
# Le Chat, DuckAssistBot for DuckDuckGo's AI answers). They read only their own
# group, never `*`, so without one of their own they would inherit nothing
# here. Same rules as every other AI stanza: public content open, /share/
# closed as duplicate content, endpoints closed, the public price ladder open.
User-agent: Claude-User
Allow: /
Disallow: /api/
Allow: /api/pricing
Disallow: /bff/
Disallow: /auth/
Disallow: /share/
Disallow: /panda/
Disallow: /login
Disallow: /cdn-cgi/
Disallow: /*?_rsc=
User-agent: Claude-SearchBot
Allow: /
Disallow: /api/
Allow: /api/pricing
Disallow: /bff/
Disallow: /auth/
Disallow: /share/
Disallow: /panda/
Disallow: /login
Disallow: /cdn-cgi/
Disallow: /*?_rsc=
User-agent: DuckAssistBot
Allow: /
Disallow: /api/
Allow: /api/pricing
Disallow: /bff/
Disallow: /auth/
Disallow: /share/
Disallow: /panda/
Disallow: /login
Disallow: /cdn-cgi/
Disallow: /*?_rsc=
User-agent: MistralAI-User
Allow: /
Disallow: /api/
Allow: /api/pricing
Disallow: /bff/
Disallow: /auth/
Disallow: /share/
Disallow: /panda/
Disallow: /login
Disallow: /cdn-cgi/
Disallow: /*?_rsc=
# Sitemap (dynamically generated by the backend - sitemap index)
Sitemap: https://insideralpha.ai/sitemap.xml
# LLM guidance (llms.txt standard): https://insideralpha.ai/llms.txt