A complete Claude API proxy new implementation that supports the full Claude API surface, including Models API, Token Counting API, and extended thinking support.
-
Complete Claude API Support: Full implementation of Claude API endpoints:
GET /v1/models- List available modelsPOST /v1/messages- Send messages with extended thinking supportPOST /v1/messages/count_tokens- Count tokens in messages
-
Extended Thinking Support: Built-in support for Claude's thinking configuration with budget tokens
-
Dynamic Routing: Route requests to any OpenAI-compatible API using URL patterns:
/https/api.qnaigc.com/v1/models/https/api.qnaigc.com/v1/messages/https/api.qnaigc.com/openai/v1/models/deepseek-v3.1/v1/messages/https/api.qnaigc.com/v1/messages/count_tokens/https/api.qnaigc.com/openai/v1/models/deepseek-v3.1/v1/messages/count_tokens
-
TypeScript First: Full type safety with comprehensive Claude and OpenAI type definitions
-
Cloudflare Workers Ready: Optimized for deployment on Cloudflare's global network
cd claude_proxy_v3
npm installEdit src/server.ts or wrangler.toml to set your environment variables:
Counting tokens with local tiktoken(default model cl100k_base) when setting LOCAL_TOKEN_COUNTING to true
or consuming tokens from the upstream API to response with 'usage' field.
[vars]
LOCAL_TOKEN_COUNTING = "false"npm run devor
npm install typescript
npx tsc -p tsconfig.server.json
LOCAL_TOKEN_COUNTING=true npx tsx dist/server.js
#node dist/server.jsRefer to Dockerfile
Build
sudo docker build -t claude-proxy-v3 .If pending at RUN npm install ...,
Edit /etc/docker/daemon.json:
{
"dns": ["8.8.8.8", "8.8.4.4"]
}Then restart Docker:
sudo systemctl restart dockerRun it
sudo docker run -p 8788:8788 claude-proxy-v3# npm run deployHigh performance deploy advices
Run like a cluster
# npm install -g pm2
# npx tsc -p tsconfig.server.json
# pm2 start dist/server.js -i 4
# pm2 ls
# pm2 stop all
# or
LOCAL_TOKEN_COUNTING=true npx tsx dist/server.js
npm run build && npm run startcomparing and testing API
bash tests/test_v1_messages_api.sh
bash tests/test_all_models.sh
bash tests/test_shell.sh
bash tests/test_shell_sse.shDesigning, Implementation, Reviewing, Testing docs are all generated with Claude Code + DeepSeek-V3.2, these md files are listed in docs.
Endpoint: GET /v1/models
List available models from the target API.
Example URL:
/GET /https/api.qnaigc.com/openai/v1/models/v1/models
/GET /https/api.qnaigc.com/v1/models
Response:
{
"data": [
{
"id": "deepseek-v3.1",
"type": "model",
"created_at": "2024-01-01T00:00:00Z",
"display_name": "DeepSeek-V3.1"
}
],
"first_id": "deepseek-v3.1",
"has_more": false,
"last_id": "deepseek-v3.1"
}Endpoint: POST /v1/messages
Send messages with optional thinking configuration.
Example URL:
/POST /https/api.qnaigc.com/v1/messages
Request with Thinking:
{
"model": "deepseek-v3.1",
"messages": [
{
"role": "user",
"content": "What is the capital of France?"
}
],
"max_tokens": 1000,
"thinking": {
"type": "enabled",
"budget_tokens": 10000
}
}Response:
{
"id": "msg_123456789",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "The capital of France is Paris."
}
],
"model": "deepseek-v3.1",
"stop_reason": "end_turn",
"usage": {
"input_tokens": 10,
"output_tokens": 5
}
}Endpoint: POST /v1/messages/count_tokens
Count tokens in messages, including thinking configuration.
Example URL:
/POST /https/api.qnaigc.com/v1/messages/count_tokens
Request:
{
"model": "deepseek-v3.1",
"messages": [
{
"role": "user",
"content": "What is the capital of France?"
}
],
"thinking": {
"type": "enabled",
"budget_tokens": 10000
}
}Response:
{
"type": "token_count",
"input_tokens": 10,
"cache_creation_input_tokens": 0,
"cache_read_input_tokens": 0
}The proxy uses dynamic routing to forward requests to any OpenAI-compatible API.
Fixed routing /v1/messages requests to /v1/chat/completions, disable routing /v1/messages requests to upstream /v1/messages.
Refer to src/handlers/messages.ts
targetUrl = targetUrl.replace('v1/messages', 'v1/chat/completions')
/{protocol}/{host}/{path_prefix}/{model_id?}/{claude_endpoint}
/{protocol}/{host}/{claude_endpoint}
-
List models:
GET /https/api.qnaigc.com/v1/models -
Send message:
POST /https/api.qnaigc.com/v1/messages -
Count tokens with Google Gemini:
POST /https/generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-exp/v1/messages/count_tokens
Forward authentication headers from the original request:
Authorization: Bearer <token>x-api-key: <key>
src/
βββ index.ts # Main router and middleware
βββ handlers/
β βββ messages.ts # Messages API handler
β βββ models.ts # Models API handler
β βββ token-counting.ts # Token counting handler
βββ converters/
β βββ claude-to-openai.ts # Request conversion
β βββ openai-to-claude.ts # Response conversion
β βββ streaming.ts # Streaming response conversion
βββ utils/
β βββ routing.ts # Dynamic routing logic
β βββ validation.ts # Request validation
β βββ errors.ts # Error handling
β βββ thinking.ts # Thinking utilities
βββ types/
βββ claude.ts # Claude API types
βββ openai.ts # OpenAI API types
βββ shared.ts # Shared types
- Router Middleware: Parses URLs, handles authentication, routes to handlers
- Converters: Convert between Claude and OpenAI API formats
- Validation: Comprehensive request validation with Claude API error formats
- Error Handling: Claude API-compatible error responses
npm run typechecknpm run dev# List models
curl -X GET "http://localhost:8787/https/api.qnaigc.com/v1/models" \
-H "Authorization: Bearer your-api-key"
# Send message
curl -X POST "http://localhost:8787/https/api.qnaigc.com/v1/messages" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-api-key" \
-d '{
"messages": [{"role": "user", "content": "Hello"}],
"max_tokens": 1000
}'MIT
- Fork the repository
- Create a feature branch
- Make your changes
- Submit a pull request