Cloudflare WAF API Reference
Pass Cloudflare WAF managed challenges and replay the cf_clearance cookie.
The Captcha.fun Cloudflare WAF API accepts kind, url and returns cf_clearance cookie. Send the API_KEY header, create a solve with POST /v1/request, then poll GET /v2/response/{id} until ready is true.
What you’ll need
- Your API key
- The URL of the page where the challenge appears
- Optional:
challengeHtml - A proxy, if the result must come from your own IP (
cf_waf_proxy)
Good to Know
Passes the Cloudflare managed challenge and returns the cf_clearance cookie together with the full Cookie header of the solve.
By default the challenge served for your target URL is used. If your integration captured the challenge page HTML, pass it in challengeHtml.
Important: The clearance is bound to the user agent and IP. If you replay from a different IP, use a _proxy kind with a sticky proxy.
Send the Challenge
Send the page details with your API key. You get a solve id back right away.
https://api.captcha.fun/v1/requestcurl -X POST https://api.captcha.fun/v1/request \
-H "API_KEY: CAPFUN-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"kind": "cf_waf",
"url": "https://your-domain.example/protected-page"
}'import requests
response = requests.post(
"https://api.captcha.fun/v1/request",
headers={
"API_KEY": "CAPFUN-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"Content-Type": "application/json",
"Accept": "application/json",
},
json={"kind": "cf_waf", "url": "https://your-domain.example/protected-page"},
)
print(response.status_code, response.json())const response = await fetch("https://api.captcha.fun/v1/request", {
method: "POST",
headers: {
"API_KEY": "CAPFUN-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"Content-Type": "application/json",
"Accept": "application/json"
},
body: JSON.stringify({
"kind": "cf_waf",
"url": "https://your-domain.example/protected-page"
})
});
console.log(response.status, await response.json());Response
Returns the solve id. Use it to get the result.
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"message": "Started Solving"
}{
"message": "invalid kind"
}Request fields5 body fields · 2 required
Wait for the Result
Use the solve id to fetch the result.
https://api.captcha.fun/v2/response/{id}Poll every second until ready is true.
https://api.captcha.fun/v1/response/{id}Long polling: the request stays open until the solve finishes or times out. Send it once and wait.
Example
curl -X GET https://api.captcha.fun/v2/response/550e8400-e29b-41d4-a716-446655440000 \
-H "API_KEY: CAPFUN-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Accept: application/json"import requests
response = requests.get(
"https://api.captcha.fun/v2/response/550e8400-e29b-41d4-a716-446655440000",
headers={
"API_KEY": "CAPFUN-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"Accept": "application/json"
}
)
print(response.status_code, response.json())const response = await fetch(
"https://api.captcha.fun/v2/response/550e8400-e29b-41d4-a716-446655440000",
{
method: "GET",
headers: {
"API_KEY": "CAPFUN-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"Accept": "application/json"
}
}
);
const data = await response.json();
console.log(response.status, data);package main
import (
"encoding/json"
"fmt"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.captcha.fun/v2/response/550e8400-e29b-41d4-a716-446655440000", nil)
req.Header.Set("API_KEY", "CAPFUN-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
req.Header.Set("Accept", "application/json")
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
fmt.Println(resp.StatusCode, result)
}import java.net.http.*;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.captcha.fun/v2/response/550e8400-e29b-41d4-a716-446655440000"))
.header("API_KEY", "CAPFUN-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
.header("Accept", "application/json")
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode() + " " + response.body());
}
}using System.Net.Http;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("API_KEY", "CAPFUN-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
client.DefaultRequestHeaders.Add("Accept", "application/json");
var response = await client.GetAsync("https://api.captcha.fun/v2/response/550e8400-e29b-41d4-a716-446655440000");
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine($"{(int)response.StatusCode} {result}");Response
{
"ready": true,
"status": "SUCCESS",
"success": true,
"userAgent": "RETURNED_USER_AGENT",
"secUa": "RETURNED_SEC_CH_UA",
"token": "v1e3b1f2e8e1a897de2ea1fa5db0d2fd8-1735689600-1.2.1...",
"cookies": {
"cf_clearance": "v1e3b1f2...",
"__cf_bm": "a1b2c3d4e5..."
},
"cookieHeader": "cf_clearance=v1e3b1f2...; __cf_bm=a1b2c3d4e5..."
}{
"message": "API_KEY Header Missing"
}Example
curl -X GET https://api.captcha.fun/v1/response/550e8400-e29b-41d4-a716-446655440000 \
-H "API_KEY: CAPFUN-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Accept: application/json"import requests
response = requests.get(
"https://api.captcha.fun/v1/response/550e8400-e29b-41d4-a716-446655440000",
headers={
"API_KEY": "CAPFUN-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"Accept": "application/json"
}
)
print(response.status_code, response.json())const response = await fetch(
"https://api.captcha.fun/v1/response/550e8400-e29b-41d4-a716-446655440000",
{
method: "GET",
headers: {
"API_KEY": "CAPFUN-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"Accept": "application/json"
}
}
);
const data = await response.json();
console.log(response.status, data);package main
import (
"encoding/json"
"fmt"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET", "https://api.captcha.fun/v1/response/550e8400-e29b-41d4-a716-446655440000", nil)
req.Header.Set("API_KEY", "CAPFUN-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
req.Header.Set("Accept", "application/json")
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
fmt.Println(resp.StatusCode, result)
}import java.net.http.*;
import java.net.URI;
public class Main {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.captcha.fun/v1/response/550e8400-e29b-41d4-a716-446655440000"))
.header("API_KEY", "CAPFUN-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
.header("Accept", "application/json")
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode() + " " + response.body());
}
}using System.Net.Http;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("API_KEY", "CAPFUN-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
client.DefaultRequestHeaders.Add("Accept", "application/json");
var response = await client.GetAsync("https://api.captcha.fun/v1/response/550e8400-e29b-41d4-a716-446655440000");
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine($"{(int)response.StatusCode} {result}");Response
{
"status": "SUCCESS",
"success": true,
"userAgent": "RETURNED_USER_AGENT",
"secUa": "RETURNED_SEC_CH_UA",
"token": "v1e3b1f2e8e1a897de2ea1fa5db0d2fd8-1735689600-1.2.1...",
"cookies": {
"cf_clearance": "v1e3b1f2...",
"__cf_bm": "a1b2c3d4e5..."
},
"cookieHeader": "cf_clearance=v1e3b1f2...; __cf_bm=a1b2c3d4e5..."
}{
"message": "API_KEY Header Missing"
}Request and response fields9 response fields
Send the Cookies
- Replay cookieHeader as the Cookie header on outbound requests to the protected origin, with the returned userAgent as your User-Agent header. The clearance is bound to both the user agent and the egress IP of the solving session.
- Prefer the full cookieHeader value over rebuilding a cookie jar from parts — the zone typically pairs cf_clearance with a __cf_bm sibling the edge expects to travel with it.
When using a successful result, preserve the returned userAgent as User-Agent and secUa as Sec-CH-UA.
Wrong or rejected result? Report the failed solve.