Rotate exit IPs across multiple Cloudflare Workers so a single machine can use multiple API keys without upstream bans or rate limits caused by a shared IP.
Client -> Router Worker -> Proxy Worker #N -> Upstream API
- You send a request to the router with a password, a proxy number, and the target URL (base64-encoded).
- The router picks a proxy worker (
proxy_num % N) and forwards internally. - The proxy worker strips all identifying headers, injects a deterministic fake IP, and calls the upstream API.
- The response (including SSE streams) passes through untouched.
Each proxy worker gets a unique but stable fake IP per upstream domain -- no storage, no state.
POST https://router.example.com/{PASSWORD}/{PROXY_NUM}/{BASE64_URL}/{extra_path}
| Segment | Example | Description |
|---|---|---|
| PASSWORD | yourpassword |
Checked against AUTH_KEY |
| PROXY_NUM | 3 |
Worker selection (modulo N) |
| BASE64_URL | aHR0cHM6Ly9hcGkub3BlbmFpLmNvbS92MQ |
URL-safe base64 of upstream base URL |
| extra_path | chat/completions |
Appended to decoded base URL |
POST https://router.example.com/yourpassword/3/aHR0cHM6Ly9hcGkub3BlbmFpLmNvbS92MQ/chat/completions
Authorization: Bearer sk-your-api-key
Content-Type: application/json
{"model":"gpt-4","messages":[...],"stream":true}
Decoded: proxy #3 calls https://api.openai.com/v1/chat/completions with your key and a stable fake IP.
Navigate to https://router.example.com/{PASSWORD} in a browser to get a client-side URL encoder page. It's behind auth so you can bookmark it. The page shows your real password in the generated URLs.
Passed through to upstream: Authorization, Content-Type, Accept, request body.
Stripped: All Cloudflare headers (CF-Connecting-IP, CF-RAY, etc.), X-Real-IP, Host.
Injected: X-Forwarded-For with the deterministic fake IP.
cp .env.example .env
# Edit .env -- set AUTH_KEY and INTERNAL_AUTH_SECRET
npm installGenerate a secret:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"npm run deployDeploys 3 proxy workers + 1 router worker to Cloudflare. Configs are generated into dist/ for inspection.
Adjust PROXY_COUNT in .env to change the number of proxy workers.
Set the base URL to:
https://router.example.com/{PASSWORD}/{PROXY_NUM}/{BASE64_URL}
For OpenAI with proxy rotation, encode the base URL:
node -e "console.log(Buffer.from('https://api.openai.com/v1').toString('base64url'))"Then set base URL to https://router.example.com/yourpassword/1/<encoded>/.
Use different PROXY_NUM values (1, 2, 3, ...) to rotate through different exit IPs.
npm test # Run tests
npm run type-check # TypeScript check
npm run dev # Local dev serversrc/
worker.ts Entry point -- dispatches by WORKER_ROLE
router.ts Auth, proxy selection, URL decode, encoder page
proxy.ts Header strip, fake IP injection, upstream call
public.ts URL encoder helper page (behind auth)
fake-ip.ts SHA-256 based deterministic IP generation
base64url.ts URL-safe base64 encode/decode
http.ts Response helpers (CORS, error JSON)
scripts/
deploy.ts Auto-generates TOML configs and deploys all workers