Claude Code User Agent String and How to Find It in Logs
Claude Code's fetch tool sends a versioned Claude-User string from the developer's own network. Our captured headers, the IP result and log commands.
- claude-code
- claude-user
- user-agent
- server-logs
- robots-txt
- ai-agents
The Claude Code user agent is Claude-User (claude-code/2.1.316; +https://support.anthropic.com/). We captured it on 31 Oct 2026 when Claude Code's web fetch tool requested a test endpoint. The request left from the developer's own computer, outside Anthropic's 14 published crawler prefixes, so an IP check will not confirm it.
As of 31 Oct 2026.
Picture a quiet page on your site. In your access log, one line carries a user agent you have never seen, and the visitor's address belongs to a home or office network:
203.0.113.77 - - [31/Oct/2026:14:02:11 +0000] "GET /docs/setup HTTP/2.0" 200 8412 "-" "Claude-User (claude-code/2.1.316; +https://support.anthropic.com/)"
That line is an invented example in the real format. It is not a crawler visit and not a person browsing. A developer asked a coding assistant to read your page, and the tool fetched it. The sections below show what such a request carries, which parts you can trust and what you can do about it.
What does a Claude Code request actually send?
On 31 Oct 2026 we asked Claude Code's WebFetch tool to request https://httpbin.org/headers, a public service that echoes the request headers back. The tool summarizes pages with a model call, so we told it to return the body verbatim. An earlier run the same day showed the same three values.
| Header | Value seen on 31 Oct 2026 |
|---|---|
| User-Agent | Claude-User (claude-code/2.1.316; +https://support.anthropic.com/) |
| Accept | text/markdown, text/html, */* |
| Accept-Encoding | gzip, compress, deflate, br |
A second request, to https://httpbin.org/user-agent, returned the same User-Agent value.
Method and limits. Period: 31 Oct 2026. Sample: two requests from one installation, version 2.1.316, on one computer. Other versions, platforms or fetch paths may send different strings. Match on the stable parts (Claude-User and claude-code/) and treat the version number as a variable.
The string differs from the Claude-User format that our guide to detecting ClaudeBot observed in server logs, which ends in Claude-User/1.0; +claude-user@anthropic.com. That format is something we saw, not something Anthropic documents. Two formats share one product token. Which one comes from the crawler and which from a developer tool?
Does the request come from Anthropic's published IP ranges?
Not in our test. Anthropic's crawler article says: "If a crawler has a source IP address on this list, it indicates that the crawler is coming from Anthropic." The list is the JSON file at claude.com/crawling/bots.json. On 31 Oct 2026 it held 14 IPv4 prefixes and a creation time of 2026-10-20.
We asked WebFetch to request https://httpbin.org/ip, which echoes the sender's address, and compared the result with the 14 prefixes in a script. The address was outside all of them. It was identical to the address that curl https://httpbin.org/ip returned from the same computer. We do not print it here. The fetch left from the developer's own network, which can be a home connection, an office, a VPN or a CI runner.
For your logs this means a passed IP check and a Claude Code request do not go together in our test: the request that carried the Claude Code string failed the check. We tested one computer and did not test other ways of running Claude Code, so treat a failed check as expected for this string rather than as proof of a fake. The IP verification tool runs the check for a single address, and GPTBot IP ranges shows the same list-matching method for OpenAI. What does the Accept header on these requests add?
What does "Accept: text/markdown" mean for your server?
The Accept header tells a server which response formats the client can handle. RFC 9110 says: "The "Accept" header field can be used by user agents to specify their preferences regarding response media types." Claude Code lists text/markdown first, then text/html, then */*.
None of the three carries a weight, and RFC 9110 sets "the default weight is 1", so the list does not rank Markdown above HTML. It does show that the client accepts Markdown. A server that does content negotiation can answer the same URL with a Markdown version. If it returns HTML, Claude Code's documentation says the tool "converts the response to Markdown when the server returns HTML", so both outcomes work for the tool. This is a statement about format, not about visibility or ranking: we have no evidence that serving Markdown changes whether a page is used.
For your logs, the practical value is a second signal. A browser sends text/html,application/xhtml+xml,... in its Accept header, so an Accept value that starts with text/markdown points to a tool rather than a browser. The default access log format does not record Accept, so add $http_accept to a custom nginx log format if you want it. Is the same true for the other coding assistants?
How do Gemini CLI, Codex, Cursor and Copilot compare?
Only some of them expose a fetch signature in public sources. We read the open-source repositories and the vendor page named below on 31 Oct 2026.
| Tool | What we found | Source |
|---|---|---|
| Claude Code | Measured: Claude-User (claude-code/2.1.316; +https://support.anthropic.com/) |
Own test above |
| Gemini CLI | Mozilla/5.0 (compatible; Google-Gemini-CLI/1.0; +https://github.com/google-gemini/gemini-cli), set as the User-Agent in the code that fetches a URL directly |
packages/core/src/tools/web-fetch.ts, line 44, commit 6814e00 (30 Oct 2026) |
| OpenAI Codex CLI | Its own HTTP client builds a User-Agent of the form codex_cli_rs/<version> (OS version; architecture) plus a terminal token. The tool spec declares a web_search tool. We found no code in the two files we read that sets a User-Agent for fetching arbitrary pages |
codex-rs/login/src/auth/default_client.rs, codex-rs/tools/src/tool_spec.rs, commit 67f0994 (31 Oct 2026) |
| Cursor | Not documented in the pages we read | none |
| GitHub Copilot coding agent (the docs page now says Copilot cloud agent) | The firewall page we read does not mention a user agent | GitHub Docs, see Sources |
Gemini CLI's file also labels the direct fetch a fallback: its prompt says "I was unable to access the URL(s) directly using the primary fetch tool." The same string is used in an experimental direct-fetch mode, so a page request from Gemini CLI may or may not carry it. For Codex, the files we read do not say which party makes a web_search page request, and we did not capture one, so we make no claim about its source address or user agent.
So a user agent alone does not identify "an AI coding tool". Claude Code is the one case here where we captured the string ourselves and it names a product token. Where can you see it in practice?
How do you find these requests in your logs and control them?
These commands assume the nginx or Apache combined log format. The example lines use documentation address ranges.
# Claude Code fetch-tool requests (the stable part of the string)
grep -F 'Claude-User (claude-code/' access.log
# Count by Claude Code version
grep -oE 'claude-code/[0-9.]+' access.log | sort | uniq -c | sort -rn
# Requests per path, separating the CLI string from the crawler string
awk -F'"' '/Claude-User/ {
kind = ($6 ~ /claude-code\//) ? "claude-code" : "claude-user-crawler";
split($2, req, " "); print kind, req[2] }' access.log | sort | uniq -c | sort -rn | head
We ran the commands on a five-line sample log we wrote ourselves: invented lines in the real format, three with the Claude Code string, one with the crawler string, one browser. The first command matched 3 lines. The second printed 2 claude-code/2.1.316 and 1 claude-code/2.1.300. The third printed:
2 claude-code /docs/setup
1 claude-user-crawler /docs/setup
1 claude-code /docs/api
On robots.txt, Anthropic's crawler article says: "Anthropic's Bots respect “do not crawl” signals by honoring industry standard directives in robots.txt." It also says "Claude-User allows site owners to control which sites can be accessed through these user-initiated requests." The article lists ClaudeBot, Claude-User and Claude-SearchBot and does not mention Claude Code. We did not test whether the Claude Code fetch tool reads your robots.txt, so do not assume a User-agent: Claude-User group stops it. If you rely on a rule, test it first, as in our robots.txt check from inside Claude Code. A rule in the web server that matches the user agent is a control you can verify yourself with curl -A.
The Claude-User bot page covers the crawler side of that token.
Common follow-up questions
What is the Claude Code user agent string?
On 31 Oct 2026, Claude Code 2.1.316 sent Claude-User (claude-code/2.1.316; +https://support.anthropic.com/) from its web fetch tool. Match on Claude-User and claude-code/ and treat the version as a variable that changes with each release.
Is a Claude Code request the same as ClaudeBot?
No. Anthropic describes ClaudeBot as collecting web content that could contribute to model training, and documents Claude-User separately as the agent used when people ask Claude questions. Our test string carries the Claude-User product token, not ClaudeBot, and it came from a developer's computer, not from a crawl.
Can I verify a Claude Code request by IP address?
Not with Anthropic's list in our test. The request came from outside the 14 prefixes in bots.json and matched our own computer's address. A pass would indicate, in Anthropic's words, that the sender is Anthropic. A fail is what we saw for this tool.
Does the version number in the string matter?
It tells you which release sent the request. We saw 2.1.316 on 31 Oct 2026, and the installed Claude Code reported the same version the same day. The number will change, so match on claude-code/ and group by version only for your own reporting.
Should I serve Markdown to these requests?
You can, since the Accept header lists text/markdown first. Claude Code converts HTML to Markdown itself, so nothing breaks if you do not. We make no claim that Markdown changes how your pages are used.
Pull one Claude-like string from your own log and paste it into the user-agent lookup to see which bot it names and how to check it.
Sources
- Own test, Claude Code WebFetch against httpbin.org/headers, /user-agent and /ip, 31 Oct 2026. Last checked: 31 October 2026
- Anthropic, Does Anthropic crawl data from the web, and how can site owners block the crawler?, https://support.claude.com/en/articles/8896518-does-anthropic-crawl-data-from-the-web-and-how-can-site-owners-block-the-crawler. Last checked: 1 November 2026
- Anthropic, crawler IP list, https://claude.com/crawling/bots.json. Last checked: 1 November 2026
- Claude Code docs, Tools reference (WebFetch tool behavior), https://code.claude.com/docs/en/tools-reference. Last checked: 31 October 2026
- IETF, RFC 9110 HTTP Semantics, sections 12.4.2 and 12.5.1, https://www.rfc-editor.org/rfc/rfc9110. Last checked: 1 November 2026
- google-gemini/gemini-cli, web-fetch.ts at commit 6814e00, https://github.com/google-gemini/gemini-cli/blob/6814e00d6b148c3a1d57244d5d7040f7c541009d/packages/core/src/tools/web-fetch.ts. Last checked: 31 October 2026
- openai/codex, default_client.rs and tool_spec.rs at commit 67f0994, https://github.com/openai/codex/blob/67f0994b532b8740f14b5b738af7b7b2a915b1d6/codex-rs/login/src/auth/default_client.rs. Last checked: 31 October 2026
- GitHub Docs, Customizing or disabling the firewall for GitHub Copilot, https://docs.github.com/en/copilot/how-tos/copilot-on-github/customize-copilot/customize-the-firewall. Last checked: 1 November 2026
Checked 31 October 2026.