Claude Code sends your email address to websites
I’ll research this topic first to get the facts right before writing.## Claude Code sends your email address to websites
A developer using Claude Code on version 2.1.318 noticed something unsettling: websites contacted by the coding agent were receiving the user’s email address in the HTTP User-Agent header. The report described the consequence in unusually practical terms—dozens of scam emails a day, apparently triggered because the address was now visible to sites the tool visited.
The issue is narrow, but it exposes a much broader question for developers using AI agents: when an assistant can browse the web, run commands, read local configuration, and call third-party APIs, where exactly does your account information end up?
The important distinction is that this was not primarily a model behavior. The email address was being added by the Claude Code client as part of request metadata. The underlying model may never have explicitly placed the address into a prompt, and it may never have “decided” to share it. Claude Code still made an outbound request that included identifying information.
That distinction matters because changing models does not automatically fix the problem. The data path is often determined by the agent runtime, HTTP client, proxy configuration, and tool implementation—not by whether the underlying model is Opus, Sonnet, GPT, or Gemini.
What actually happened
The reported behavior was associated with Claude Code 2.1.318. When the tool made web requests, it included the signed-in user’s account email in the User-Agent header. The header is a conventional place for clients to describe themselves:
User-Agent: ClaudeCode/2.1.318 (email@example.com)
A User-Agent is not a secret header. Web servers, reverse proxies, CDN edge nodes, analytics systems, and request logs routinely receive and retain it. It can also be exposed to sites visited by the agent, including search providers, package registries, documentation sites, and any URL that the tool fetches.
The practical consequence is not limited to a cosmetic privacy violation. An email address becomes a durable identifier. It can be correlated with requests, associated with an account, included in marketing databases, used for targeted advertising, or harvested for phishing. The original report’s mention of scam email is particularly important: sharing an address does not merely create a theoretical disclosure. It can make a user’s address visible to an ecosystem that already has incentives to abuse it.
The issue discussion also pointed to a privacy protection introduced around version 2.1.317. The change asks before a web or shell tool operation would transmit an account email address to the network. In other words, the eventual mitigation was to add a consent boundary around a value that should not have been treated as harmless metadata.
That fix is more significant than simply removing one string from one header. It establishes a useful principle: an identifier should not cross a trust boundary merely because the tool framework considers it useful for attribution.
Why it happened
In practice, email-related identifiers tend to enter coding environments through several channels:
# Git identity
git config --global user.email
# Environment variables
env | grep -i email
# Claude Code account metadata
# Depending on the installation and login method
A developer may reasonably expect git config user.email to be used for Git commits. It is much less reasonable to expect it to be attached automatically to arbitrary web searches performed by an AI coding assistant.
The likely failure mode was a convenience feature becoming a default data flow. A client-side author may have wanted to identify Claude Code requests to help servers debug abuse, distinguish traffic, or support enterprise attribution. That is understandable. The mistake was treating an account email as a harmless technical identifier without evaluating where the request would go.
This is a common gotcha in agentic software: a value that is useful in one context becomes dangerous when the same process reuses it in another. A telemetry client may need a user ID. An authentication request may need an account identifier. A web request usually does not.
Why developers should care about AI APIs
The issue is not limited to users who browse the web interactively. Any production system that combines a model with external tools should assume that tool metadata can leak beyond the model provider.
Consider a typical coding agent pipeline:
User request
↓
Claude Code / agent runtime
↓
Model API
↓
Tool decision
↓
WebFetch, shell, browser, package manager, MCP server
↓
Third-party service
A model provider may receive only the conversation and tool schemas. But the local agent may make the final request to an external service, and that request can contain:
- The account email or user ID
- Repository name and commit messages
- Local file paths
- Error messages containing source code
- Environment-variable values
- Authentication tokens or cookies
- IP address, device information, and organization details
The key security boundary is therefore not just “model versus API.” It is “trusted application code versus every downstream destination.”
This is especially relevant for developers using AI APIs in CI/CD, support systems, coding agents, and internal tools. A prompt can be carefully scrubbed for secrets, while the surrounding HTTP client quietly adds an identifier. Or a developer may use a sanitized model endpoint but route the agent’s tool calls through a third-party service that logs headers.
A useful threat model has three layers:
| Layer | What may be exposed | Key question |
|---|---|---|
| Model API | Prompt, context, tool schemas, model output | What is sent to the provider? |
| Agent runtime | Session state, local environment, credentials, account metadata | What does the client add automatically? |
| Tool destinations | Headers, URLs, logs, cookies, request bodies | What does each third party receive? |
A privacy review that stops at the model API is incomplete.
Does a different model solve it?
No. The model choice may affect reasoning quality, latency, cost, and tool-use reliability, but it does not control whether Claude Code, Codex, Gemini CLI, or another agent wrapper adds your email to a User-Agent header.
The current model families make this distinction clearer because they support different combinations of capability and cost:
| Model | Practical role in an agent workflow | Does model choice directly fix an email-leaking HTTP header? |
|---|---|---|
| Claude Fable 5.1 | High-capability work with a large context window | No |
| Claude Opus 5.5 | Complex reasoning, architecture, and difficult multi-step tasks | No |
| Claude Sonnet 5 | Balanced performance for routine coding-agent workloads | No |
| Claude Haiku 4.5 | Lower-latency or lower-cost handling of simple tasks | No |
| GPT-6 Astra / GPT-6 Sol | Alternative agent and application workflows with different tool ecosystems | No |
| Gemini 3 | Multimodal and Google-centered application integrations | No |
A stronger model may produce better code, but it cannot sanitize a request made after the model returns a tool call. Likewise, a cheaper model does not make an unsafe client safe. The relevant architecture is:
# The model proposes a tool call
tool_call = model.generate(...)
# The runtime constructs the outbound request
headers = {
"User-Agent": build_user_agent(user),
"Authorization": f"Bearer {token}",
}
response = requests.get(
tool_call["url"],
headers=headers,
timeout=30,
)
The disclosure occurs in build_user_agent(user). The model selected the destination, but the client supplied the identifying value.
For teams that need to route requests across Claude, GPT, and Gemini models, using an API gateway or aggregation layer can simplify policy enforcement. AI Prime Tech is useful in that context for cheaper Claude/GPT/Gemini API access, especially when requests are normalized through one integration. The point is not that aggregation automatically provides privacy; it is that a single layer can enforce rules such as stripping User-Agent values, blocking sensitive headers, and recording destination-specific audit logs.
How to check and protect your environment
Start by identifying every email-like value in the agent environment:
git config --global user.email || true
git config user.email || true
env | grep -Ei '(^|_)(email|user|account|identity)' || true
Then inspect actual outbound requests rather than relying only on configuration files. A local proxy is a practical way to observe headers:
# Example: run the agent through a local proxy
HTTPS_PROXY=http://127.0.0.1:8888 claude
# Or use a custom HTTP client in a test harness
python - <<'PY'
import requests
response = requests.get(
"https://example.com",
headers={"User-Agent": "ClaudeCode/test email@example.com"},
timeout=10,
)
print(response.status_code)
PY
In a controlled test, inspect the request in a proxy log or with a local debugging server. The goal is to verify that no account email appears in:
User-Agent
Referer
X-Forwarded-For
Custom X-* headers
Query strings
Cookie values
For production teams, the stronger controls are:
- Use a generic User-Agent. Send a product name and version, not an account identity.
- Keep credentials scoped. Use short-lived tokens and separate tokens for each destination.
- Block accidental secret propagation. Maintain a denylist for email addresses, API keys, and organization identifiers.
- Log destinations, not payloads. Record the hostname, method, status, and timestamp before retaining request bodies.
- Apply tool-specific policies. A package registry, browser search, and internal API may need different headers and retention rules.
- Test the agent, not just the model. Include privacy assertions in integration tests.
A simple test can be added to a CI pipeline:
def test_outbound_headers_do_not_contain_account_email():
headers = build_headers(user_email="developer@example.com")
serialized = " ".join(f"{key}: {value}" for key, value in headers.items())
assert "developer@example.com" not in serialized
assert "email" not in serialized.lower()
The larger lesson
The Claude Code email disclosure is easy to describe as a header bug. That description is accurate, but incomplete. The deeper issue is that agentic software increasingly has two identities: the model’s context and the client’s metadata.
Even a perfectly prompted model can’t prevent the surrounding program from leaking information. Conversely, a sanitized prompt can still travel alongside an identifying header. Developers need to evaluate the full request path, including tool wrappers and third-party destinations.
The most effective fix is not merely “don’t send the email.” It is to make data minimization the default: an agent should send only what the destination requires, and should ask—or avoid the operation—before crossing a boundary with an account identifier.
Practical takeaways
- Update Claude Code to a version that includes the privacy guard around email transmission, and verify the installed version rather than assuming it is current.
- Check Git configuration and environment variables for email addresses that an agent might reuse.
- Treat every outbound tool request as part of your application’s security boundary.
- Prefer generic
User-Agentstrings over account-based attribution. - Test header propagation with a proxy, local server, or CI integration test.
- Evaluate models by capability and cost, but do not expect a model change to repair a client-side privacy flaw.
- When centralizing access to Claude, GPT, and Gemini through an API layer, add header sanitization and destination-level logging explicitly.
- Remember that an email address is personal data, even when it appears as an innocuous piece of telemetry.
One API key for Claude Opus 4.8, Sonnet 4.6, Haiku 4.5, Fable 5, plus GPT & Gemini — up to 80% off official pricing, pay-as-you-go.
Get Your API Key →