What is a reverse proxy?
A reverse proxy accesses the target site on your behalf and then returns the result. For example, instead of directly visiting example.com, you let Cloudflare Worker request it and return the response.
Typical use cases:
- Bypass geo restrictions
- Hide your real server address
- Access blocked websites
- Use your own domain to access target websites
Prerequisites
- Cloudflare account - sign up for free at https://cloudflare.com
- Wrangler CLI -
npm install -g wrangler - Wrangler login -
wrangler login
Demo project (proxying an AI public relay site)
Repository: https://github.com/evepupil/any-proxy
Live demo: any.chaosyn.com
Note: direct access only works after binding a custom domain.
Full code example
Create worker.js:
/** * Cloudflare Worker reverse proxy * Purpose: proxy anyrouter.top */
// Target websiteconst TARGET_HOST = 'anyrouter.top';const TARGET_URL = `https://${TARGET_HOST}`;
addEventListener('fetch', event => { event.respondWith(handleRequest(event.request));});
/** * Core request handler */async function handleRequest(request) { try { // 1. Parse incoming URL const url = new URL(request.url);
// 2. Build target URL (keep original path and query) const targetUrl = `${TARGET_URL}${url.pathname}${url.search}`;
// 3. Copy and adjust headers const headers = new Headers(request.headers); headers.set('Host', TARGET_HOST);
// 4. Build request options const requestOptions = { method: request.method, headers: headers, // Important: do not follow redirects automatically redirect: 'manual', };
// 5. Forward request const response = await fetch(targetUrl, requestOptions);
// 6. Handle redirect responses if ([301, 302, 303, 307, 308].includes(response.status)) { const location = response.headers.get('Location'); if (location && !location.startsWith(TARGET_HOST)) { // Forward external redirect const responseHeaders = new Headers(response.headers); responseHeaders.set('Access-Control-Allow-Origin', '*'); return new Response(response.body, { status: response.status, statusText: response.statusText, headers: responseHeaders }); } else { // Block self-redirect loops return new Response('This site does not allow proxy access', { status: 200, headers: { 'Content-Type': 'text/plain; charset=utf-8' } }); } }
// 7. Handle normal response const responseHeaders = new Headers(response.headers); responseHeaders.set('Access-Control-Allow-Origin', '*'); responseHeaders.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
// 8. Remove conflicting security headers responseHeaders.delete('Content-Security-Policy'); responseHeaders.delete('X-Frame-Options');
// 9. Return response return new Response(response.body, { status: response.status, statusText: response.statusText, headers: responseHeaders });
} catch (error) { return new Response(`Proxy failed: ${error.message}`, { status: 500, headers: { 'Content-Type': 'text/plain; charset=utf-8' } }); }}Deployment steps
Method 1: CLI (recommended)
1. Initialize project
wrangler init any-proxycd any-proxy2. Create config file wrangler.toml
name = "any-proxy"main = "worker.js"compatibility_date = "2024-01-01"workers_dev = true3. Deploy
wrangler deploy4. Get URL
After deployment, you will see output like:
Deployed any-proxy triggers (0.66 sec) https://any-proxy.your-subdomain.workers.devThat URL is your proxy endpoint.
Method 2: Dashboard
- Log in to Cloudflare Dashboard
- Go to “Workers & Pages”
- Click “Create application” → “Create Worker”
- Paste your code
- Click “Save and Deploy”
Bind a custom domain
1. Add domain in Cloudflare
If your-domain.com is managed by Cloudflare:
# Add route to wrangler.tomlroutes = [ { pattern = "your-domain.com/*", zone_name = "your-domain.com" }]2. Redeploy
wrangler deploy3. DNS settings
Cloudflare handles DNS records automatically, so manual DNS setup is usually unnecessary.
Common issues
❌ 500 error - “Too many redirects”
Cause: target site detects proxy access and keeps redirecting.
Fix: set redirect: 'manual' and handle redirects yourself (see code above).
❌ Static assets return 404
Cause: internal links are absolute URLs pointing to the origin domain.
Fix: add URL rewriting to replace origin-domain links with your proxy domain.
❌ CORS errors
Fix: include these response headers:
Access-Control-Allow-Origin: *Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONSAdvanced features
1. URL rewrite (force all resources through proxy)
// Add this in response handlingconst contentType = response.headers.get('content-type') || '';
if (contentType.includes('text/html') || contentType.includes('text/javascript') || contentType.includes('text/css')) {
const text = await response.text(); // Replace anyrouter.top with current proxy domain const rewrittenText = text.replace(/https:\/\/anyrouter\.top/g, proxyUrl);
return new Response(rewrittenText, { status: response.status, headers: responseHeaders });}2. Add caching
// Cache static assets for 1 hourconst cacheKey = new Request(url, request);const cache = caches.default;
let response = await cache.match(cacheKey);if (!response) { response = await fetch(targetUrl); // Store response in cache await cache.put(cacheKey, response.clone());}Example project structure
my-proxy/├── worker.js # Main program├── wrangler.toml # Configuration└── package.json # Dependencies (optional)Summary
- Core flow: intercept request → forward to target → adjust response → return to client
- Key points:
- Adjust request headers (Host, Origin)
- Disable auto-redirects
- Add CORS support
- Handle URL rewriting
- Deployment options: Wrangler CLI or Dashboard UI
That’s it. You can now access target websites anywhere through your Cloudflare Worker.
