Symptoms of the 401 Authentication Error
When working with the Claude API, you may encounter a frustrating 401 Invalid API Key error — whether you're just getting started or have had things running smoothly for weeks. The error typically looks like this in your terminal or logs:
{
"type": "error",
"error": {
"type": "authentication_error",
"message": "Invalid API Key"
}
}This error means the API key sent with your request was rejected. But the root cause isn't always as simple as a typo in your key. It could be a misconfigured environment variable, an expired key, a corrupted OAuth token, or even network interference.
Cause 1: API Key Not Properly Configured
The most frequent culprit is a missing or incorrect ANTHROPIC_API_KEY environment variable.
How to Check
Run this in your terminal to see what's currently set:
# Check if the environment variable exists (show first 10 characters only)
echo "${ANTHROPIC_API_KEY:0:10}..."
# If empty, the variable isn't setIf the output is blank or doesn't start with sk-ant-, there's a configuration issue.
How to Fix It
# macOS / Linux: Add to your shell config
echo 'export ANTHROPIC_API_KEY="sk-ant-api03-xxxxx..."' >> ~/.zshrc
source ~/.zshrc
# Windows (PowerShell): Set as user environment variable
[System.Environment]::SetEnvironmentVariable("ANTHROPIC_API_KEY", "sk-ant-api03-xxxxx...", "User")
# Restart PowerShell to applyCommon pitfall: You might have added the key to a .env file, but your application isn't loading it. In Python, make sure you're using python-dotenv; in Node.js, use the dotenv package. Double-check that the .env file is in the correct directory.
# Python: Verify .env file loading
import os
from dotenv import load_dotenv
load_dotenv() # Load .env file
api_key = os.getenv("ANTHROPIC_API_KEY")
if not api_key:
raise ValueError("ANTHROPIC_API_KEY is not set")
print(f"API Key found: {api_key[:10]}...")
# Expected output: API Key found: sk-ant-api...Cause 2: API Key Has Been Revoked or Expired
If someone on your team regenerated or deleted the key in the Anthropic Console, the old key becomes invalid immediately. This can happen without notice in shared workspace environments.
How to Check
- Log in to the Anthropic Console
- Navigate to the "API Keys" section
- Confirm that your key is listed and its status shows "Active"
How to Fix It
If the key is missing or inactive, create a new one and update your configuration:
# Set the new key
export ANTHROPIC_API_KEY="sk-ant-api03-your-new-key..."
# Quick verification with curl
curl -s https://api.anthropic.com/v1/messages \
-H "Content-Type: application/json" \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "claude-sonnet-4-6",
"max_tokens": 50,
"messages": [{"role": "user", "content": "Hello"}]
}' | head -c 200
# Expected output: {"id":"msg_...","type":"message","role":"assistant",...}If you get a valid response, the new key works. Don't forget to update your .env files, CI/CD secrets, and any secret management tools with the new key.
Cause 3: Incorrect Request Header Format
The Claude API uses a different authentication header than many other AI APIs. If you're coming from OpenAI, you might instinctively use Authorization: Bearer, but Claude requires the x-api-key header instead.
Common Mistake vs. Correct Approach
import anthropic
# ❌ Wrong: Using Authorization Bearer header directly
# requests.post(url, headers={"Authorization": f"Bearer {api_key}"})
# ✅ Correct: Use the Anthropic SDK (handles x-api-key automatically)
client = anthropic.Anthropic() # Reads ANTHROPIC_API_KEY from environment
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[
{"role": "user", "content": "Hello!"}
]
)
print(message.content[0].text)
# Expected output: Hello! How can I help you today?If you're making raw HTTP requests without the SDK, always include these headers:
# Required headers
-H "x-api-key: YOUR_API_KEY"
-H "anthropic-version: 2023-06-01"
-H "Content-Type: application/json"Cause 4: Claude Code OAuth Token Corruption
Claude Code (the CLI tool) uses browser-based OAuth authentication via the /login command. When this token gets corrupted, you'll see a "401 Invalid bearer token" error even though the login appeared to succeed.
Symptoms
$ claude
⎿ API Error: 401 {"type":"error","error":{"type":"authentication_error","message":"Invalid bearer token"}}
How to Fix It
Clear your credentials completely and re-authenticate:
# Step 1: Clear all authentication data
rm -rf ~/.claude/auth* 2>/dev/null
rm -rf ~/.claude/.credentials 2>/dev/null
# Step 2: Unset any API key that might conflict with OAuth
unset ANTHROPIC_API_KEY
# Step 3: Re-authenticate
claude /login
# Step 4: Complete browser auth, then verify
claude "Hello, this is a test"If the issue persists, update Claude Code to the latest version:
# Update Claude Code
npm install -g @anthropic-ai/claude-code@latest
# Check version
claude --versionCause 5: Proxy, VPN, or Firewall Interference
Corporate networks, certain countries, and VPN configurations can intercept or modify API requests, stripping or altering the authentication header before it reaches Anthropic's servers.
How to Check
# Check proxy settings
echo "HTTP_PROXY: $HTTP_PROXY"
echo "HTTPS_PROXY: $HTTPS_PROXY"
echo "NO_PROXY: $NO_PROXY"
# Direct connection test (bypass proxy)
curl -v --noproxy '*' https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{"model":"claude-sonnet-4-6","max_tokens":10,"messages":[{"role":"user","content":"Hi"}]}' \
2>&1 | grep -E "HTTP/|error|auth"How to Fix It
If the direct connection test works but proxied requests fail, add api.anthropic.com to your proxy bypass list:
# Add api.anthropic.com to proxy bypass
export NO_PROXY="api.anthropic.com,$NO_PROXY"For VPN users, temporarily disconnect and test to isolate whether the VPN is causing the problem.
Cause 6: Billing or Permission Issues
Your API key might be valid, but access can still be denied due to account-level problems:
- Zero credit balance: Pay-as-you-go accounts with no remaining credits
- Key scope restrictions: Using a key from one workspace in a different workspace
- Account suspension: The account has been suspended for policy violations
How to Check
- Log in to the Anthropic Console
- Navigate to "Billing" and check your credit balance
- Check "Settings" for account status
- Verify that the API key's workspace matches the one you're using
If your balance is depleted, adding credits will immediately restore access.
Verifying the Fix
After applying a fix, run this verification script to confirm everything is working:
import anthropic
import sys
def verify_authentication():
"""Verify Claude API authentication is working"""
try:
client = anthropic.Anthropic()
# Minimal request to test auth
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=20,
messages=[{"role": "user", "content": "Say OK"}]
)
print(f"✅ Authentication successful")
print(f" Model: {response.model}")
print(f" Response: {response.content[0].text}")
print(f" Usage: input={response.usage.input_tokens}, output={response.usage.output_tokens}")
return True
except anthropic.AuthenticationError as e:
print(f"❌ Authentication error: {e}")
print(" → Check your API key")
return False
except anthropic.APIConnectionError as e:
print(f"❌ Connection error: {e}")
print(" → Check your network settings")
return False
except Exception as e:
print(f"❌ Unexpected error: {e}")
return False
if __name__ == "__main__":
success = verify_authentication()
sys.exit(0 if success else 1)
# Expected output:
# ✅ Authentication successful
# Model: claude-sonnet-4-6
# Response: OK
# Usage: input=10, output=3Best Practices for Preventing Authentication Errors
Adopting a few good habits will save you from encountering these errors repeatedly.
Secure key management is the foundation. Never hardcode API keys in source code. Use environment variables or dedicated secret management tools like AWS Secrets Manager, HashiCorp Vault, or 1Password. In team settings, issue individual keys per developer rather than sharing a single key.
Robust error handling is equally important. Rather than blindly retrying on a 401 error, implement logic that verifies the key's validity before attempting again:
import anthropic
import time
def call_with_auth_retry(client, max_retries=2, **kwargs):
"""Retry with key re-validation on authentication errors"""
for attempt in range(max_retries + 1):
try:
return client.messages.create(**kwargs)
except anthropic.AuthenticationError:
if attempt < max_retries:
print(f"Auth error (attempt {attempt + 1}/{max_retries + 1})")
print("Reloading API key...")
# Reload from environment
import os
os.environ.pop("ANTHROPIC_API_KEY", None)
from dotenv import load_dotenv
load_dotenv(override=True)
client = anthropic.Anthropic()
time.sleep(1)
else:
raiseLooking back
The Claude API 401 authentication error is usually straightforward to resolve once you've identified the root cause. This guide covered six common patterns: missing environment variables, revoked keys, incorrect header format, corrupted OAuth tokens, proxy interference, and billing issues. Work through them in order, and you'll have your API calls running smoothly again.
The fastest troubleshooting approach: start with echo $ANTHROPIC_API_KEY to verify the key exists, then use a curl command to test directly. If that doesn't resolve things, use the Python verification script from this article.
For a comprehensive overview of error handling strategies, see our Claude API Error Handling and Retry Strategies guide. If you're just getting started with the API, our First API Call Troubleshooting FAQ covers the most common beginner pitfalls.