Connect Akto with Cloudflare
Cloudflare is a global network security platform that provides CDN, DDoS protection, and API security services. Integrating Cloudflare with Akto enables automatic discovery of all APIs passing through your Cloudflare infrastructure, helping you maintain continuous visibility and protection of your edge-distributed APIs.

To connect Akto with Cloudflare, follow these steps -
Step 1: Deploy the Akto Data-Ingestion Service
Before configuring the Cloudflare Worker Traffic Connector, you need to deploy the Akto Data-Ingestion Service. Ensure that the service is running and accessible via a publicly available URL. Set up and configure Akto Traffic Processor. The steps are mentioned here. Ensure this instance is publicly accessible, as it will receive traffic logs from your Cloudflare Worker.
Step 2: Set Up Your Cloudflare Worker Script
Navigate to the Cloudflare Dashboard and select your account.
Go to Workers & Pages.
Click Create and choose Worker.
Click the Hello World button and deploy it.
Click Edit code and replace the default script with your Worker code that proxies traffic and mirrors it to Akto using service binding.
export default { async fetch(request, env, ctx) { console.log("🚀 Worker handling:", request.method, request.url); // Detect WebSocket upgrade const upgradeHeader = request.headers.get("Upgrade") || ""; const isWebSocket = upgradeHeader.toLowerCase() === "websocket"; if (isWebSocket) { console.log("🔄 WebSocket upgrade detected"); // Just proxy the connection const response = await fetch(request); // Clone headers only (no body to tee here) ctx.waitUntil(logTraffic(request, response, env, { isWebSocket: true })); return response; } // Normal HTTP(S) traffic let requestForFetch, requestForLog; if (request.body) { const [req1, req2] = request.body.tee(); requestForFetch = new Request(request, { body: req1 }); requestForLog = new Request(request, { body: req2 }); } else { requestForFetch = request; requestForLog = request.clone(); } const response = await fetch(requestForFetch); console.log("⬅️ Upstream response:", response.status); let responseForClient, responseForLog; if (response.body) { const [res1, res2] = response.body.tee(); responseForClient = new Response(res1, response); responseForLog = new Response(res2, response); } else { responseForClient = response; responseForLog = response.clone(); } ctx.waitUntil(logTraffic(requestForLog, responseForLog, env)); return responseForClient; }, }; async function logTraffic(request, response, env, opts = {}) { try { console.log("📝 logTraffic running..."); const reqContentType = request.headers.get("content-type") || ""; const resContentType = response.headers.get("content-type") || ""; const status = response.status; let reqBody = ""; let resBody = ""; if (!opts.isWebSocket) { // Only attempt to read bodies for HTTP reqBody = await readBodyAsText(request); resBody = await readBodyAsText(response); if (!(status >= 200 && status < 400)) { console.log("⚠️ Skipped log: status", status); return; } if (!reqContentType && !resContentType) { console.log("⚠️ Skipped log: no content-type in request or response"); return; } if (!shouldCapture(reqContentType) && !shouldCapture(resContentType)) { console.log("⚠️ Skipped log: not a target content-type", { reqContentType, resContentType }); return; } } const url = new URL(request.url); const logEntry = { path: url.pathname, method: request.method, requestHeaders: JSON.stringify(Object.fromEntries(request.headers)), responseHeaders: JSON.stringify(Object.fromEntries(response.headers)), requestPayload: reqBody, responsePayload: resBody, ip: request.headers.get("cf-connecting-ip") || "127.0.0.1", time: Math.floor(Date.now() / 1000).toString(), statusCode: status.toString(), type: opts.isWebSocket ? "WebSocket" : "HTTP/1.1", status: response.statusText || "OK", akto_account_id: "1000000", akto_vxlan_id: "0", is_pending: "false", source: "MIRRORING", }; console.log("📤 Sending log entry to webhook..."); const aktoReq = new Request("https://<DATA_INGESTION_SERVICE>/api/ingestData", { method: "POST", headers: { "content-type": "application/json", "x-api-key": "YOUR_AKTO_API_KEY" }, body: JSON.stringify({ batchData: [logEntry] }), }); // await env.<CONTAINER_BINDING_VARIABLE_NAME>.fetch(aktoReq); await fetch(aktoReq); console.log("✅ Log sent"); } catch (err) { console.error("❌ Log error:", err); } } function shouldCapture(contentType) { const targets = ["json", "xml", "x-www-form-urlencoded", "soap", "grpc"]; return targets.some((t) => contentType.toLowerCase().includes(t)); } async function readBodyAsText(obj, maxSize = 64 * 1024) { try { const buf = await obj.arrayBuffer(); const bytes = new Uint8Array(buf).slice(0, maxSize); return new TextDecoder().decode(bytes); } catch { return ""; } }
Important Notes while editing the Worker code
Replace
<DATA_INGESTION_SERVICE>
with the URL of the Akto Data-Ingestion Service you deployed in Step 1.Replace
YOUR_AKTO_API_KEY
with your API key from Akto. You can find it inside Akto Dashboard → Settings → Integrations → Akto API.If you are using Cloudflare Service Binding to send traffic to your ingestion service hosted inside a Cloudflare container, use the following line instead of a public URL:
// use this line to send data internally to data ingestion service // hosted in your Cloudflare container await env.<CONTAINER_BINDING_VARIABLE_NAME>.fetch(aktoReq); // for example await env.data_inject_worker.fetch(aktoReq);
Step 3: Configure Worker Routing
If you'd like to route specific domains or paths through this Worker:
In the Cloudflare Dashboard, go to Workers & Pages.
Under Overview, select your Worker.
Navigate to Settings > Domains & Routes.
Click Add Route.
Select the appropriate zone (domain), and enter a route pattern such as:
*.yourdomain.com/*
This ensures all traffic matching the route is intercepted and mirrored to Akto.
Step 4: Verify the Setup
Confirm that API traffic data (requests and responses) are captured on the Akto dashboard under the respective API collection.
Check logs of your Worker for any initialization or forwarding messages.
Go back to the Akto Dashboard.
Navigate to API Collections > Hostname.
You should start seeing the traffic from your Cloudflare Worker.
Get Support for your Akto setup
There are multiple ways to request support from Akto. We are 24x7 available on the following:
In-app
intercom
support — message us inside the Akto dashboard and someone will reply.Join our discord channel for community support.
Contact
[email protected]
for email support.Reach us here.
Last updated
Was this helpful?