NullFlare

API reference

NullFlare API

The API solves Turnstile widgets and Cloudflare WAFv3 interstitial challenges. All solves are synchronous.

POST https://api.nullflare.com/
Content-Type: application/json

Authentication is the key property in the JSON body. Keep API keys on your server; do not ship one in browser JavaScript.

Turnstile

Use Turnstile mode for a widget embedded in a page. The sitekey and host must belong together.

Request

{
  "key": "YOUR_KEY",
  "sitekey": "0x4AAAAAAAExampleSitekey",
  "host": "https://example.com/login"
}

Success

{
  "status": "ok",
  "token": "1.p5ESTZJ-kUZ46gYsJBAdzcVuf8Rysl...",
  "elapsedMs": 4503,
  "remaining": 9814
}

A Turnstile solve uses 1 credit.

Submit token to the target site in the field it uses for the widget response, normally cf-turnstile-response. Tokens are short-lived and single-use.

If the widget supplies action, cData, or chlPageData, send the same values. An interactive challenge is handled inside the solve; the request and response shapes do not change.

WAFv3

Use WAFv3 mode when a URL returns Cloudflare's challenge page (the “Just a moment…” interstitial) instead of the protected page. Do not provide a sitekey. The solver reads it from the challenge itself.

Request

{
  "key": "YOUR_KEY",
  "type": "WAFv3",
  "host": "https://example.com/protected",
  "proxy": "http://user:[email protected]:8080"
}

host is the URL that is currently showing the challenge.

Send a proxy with every WAFv3 solve, and use the same one for the requests that follow. Cloudflare ties the clearance to the address that solved it. Without a proxy, the solve runs from NullFlare's own address and the clearance is useless from yours. Use a sticky session proxy, not one that rotates per request.

Success

{
  "status": "ok",
  "token": "cf_clearance value",
  "cfClearance": "cf_clearance value",
  "userAgent": "Mozilla/5.0 ... Chrome/...",
  "cookies": {
    "cf_clearance": "...",
    "__cf_bm": "..."
  },
  "elapsedMs": 8217,
  "remaining": 9812
}

A WAFv3 clearance uses 2 credits: it runs the interstitial and its embedded Turnstile widget.

token and cfClearance contain the same clearance value. token remains for clients that expect one result field; new WAFv3 integrations should use the named session fields.

Using the session

  1. Send the next request with the exact returned userAgent.
  2. Send every entry in cookies, not only cf_clearance. Some zones also issue __cf_bm or other cookies.
  3. Use the same proxy that was used for the solve.
  4. Request the challenged URL again. Preserve the returned session for later requests to the same zone until it expires.

A WAFv3 result is a session bundle. Mixing its cookie with a different User-Agent, cookie jar, or network identity can invalidate the clearance.

Request fields

FieldRequiredDescription
keyAlwaysClient API key.
typeWAFv3 onlyTurnstile is the default. Set this to WAFv3 for an interstitial challenge. Matching is case-insensitive.
hostAlwaysFull page URL. For Turnstile, this is the page containing the widget. For WAFv3, this is the challenged URL.
sitekeyTurnstile onlyWidget sitekey. Omit it for WAFv3.
proxyWAFv3Turnstile: optionalPer-solve proxy. Every network request made by that solve uses it. See Proxies.
actionWhen supplied by widgetTurnstile action string from the widget configuration.
cDataWhen supplied by widgetTurnstile custom data. Preserve its exact value and casing.
chlPageDataWhen supplied by widgetTurnstile page data. Preserve its exact value and casing.

The request body must be a JSON object and may not exceed 256 KiB. Unknown fields are ignored, but relying on that is not part of the API contract.

Response contract

Responses produced by the API are JSON. Read the HTTP status before interpreting the body.

FieldMeaning
statusok on success, error for a rejected or failed solve, and busy when capacity is temporarily unavailable.
tokenTurnstile response token, or the WAFv3 cf_clearance value.
elapsedMsSolver time in milliseconds.
remainingCredits left on the key after this request. It is null for an unlimited key.
errorPublic error description. Present on unsuccessful responses.
errorCodeStable machine-readable reason when the response has one, such as concurrency_limit, solve_failed, or node_unavailable.
cfClearanceWAFv3 only. The clearance cookie value.
userAgentWAFv3 only. Browser identity bound to the session.
cookiesWAFv3 only. Complete cookie jar observed during that solve.

Errors and retries

HTTPChargedWhat to do
400NoFix malformed JSON, missing fields, an invalid proxy, or another rejected input. Do not retry unchanged.
401NoThe key is missing or unknown. Correct the key.
402NoThe key does not have enough credits for this solve type.
403NoThe key is suspended. Contact the key administrator.
413NoThe request body is larger than 256 KiB.
422NoThe solve ran but produced no token or clearance (solve_failed). A retry is a new solve.
429NoThis key reached its simultaneous-solve limit. The body includes concurrencyLimit and inFlight. Wait for Retry-After, then retry.
503NoThe fleet is full, unavailable, or updating. Wait for Retry-After, then retry.

Only successful solves are charged. Credits are reserved when a request is accepted and returned on every outcome other than a token or clearance, including 422.

If the connection is lost after the API accepts a request, its outcome may be unknown. Solve requests are not idempotent: retrying starts another solve, and both are charged if both succeed. HTTP 502, 504, and Cloudflare 52x pages originate between the client and this API rather than from the JSON API contract.

Proxies

http://host:port
https://host:port
socks4://host:port
socks5://host:port

http://username:password@host:port
socks5://host:port:username:password

Both credential forms are accepted. In the colon form, everything after the username is treated as the password, so passwords may contain colons. SOCKS hostname resolution occurs at the proxy by default.

The proxy must tunnel the connection (HTTP CONNECT or SOCKS). A proxy that terminates TLS itself changes the browser fingerprint the challenge scores, and solves through it fail.

Credits and concurrency

Credits cost $0.40 per 1,000. A Turnstile token uses 1 credit and a WAFv3 clearance uses 2. To buy credits or get a key, email [email protected] or ask on Discord.

Credits and simultaneous work are separate limits:

A client that fills its own concurrency slots receives 429. It does not consume another slot or prevent other keys from using the service.

Client examples

Turnstile with curl

curl https://api.nullflare.com/ \
  --header 'Content-Type: application/json' \
  --data '{
    "key":"YOUR_KEY",
    "sitekey":"0x4AAAAAAAExampleSitekey",
    "host":"https://example.com/login"
  }'

Turnstile with Python

import os
import requests

response = requests.post(
    "https://api.nullflare.com/",
    json={
        "key": os.environ["NULLFLARE_KEY"],
        "sitekey": "0x4AAAAAAAExampleSitekey",
        "host": "https://example.com/login",
    },
    timeout=110,
)
result = response.json()
response.raise_for_status()
token = result["token"]

WAFv3 with server-side JavaScript

import { ProxyAgent } from "undici";

const proxy = process.env.OUTBOUND_PROXY;
const solveResponse = await fetch("https://api.nullflare.com/", {
  method: "POST",
  headers: { "content-type": "application/json" },
  body: JSON.stringify({
    key: process.env.NULLFLARE_KEY,
    type: "WAFv3",
    host: "https://example.com/protected",
    proxy,
  }),
  signal: AbortSignal.timeout(110_000),
});

const session = await solveResponse.json();
if (!solveResponse.ok) throw new Error(session.error);

const cookie = Object.entries(session.cookies)
  .map(([name, value]) => `${name}=${value}`)
  .join("; ");

const protectedResponse = await fetch("https://example.com/protected", {
  dispatcher: new ProxyAgent(proxy),
  headers: {
    "user-agent": session.userAgent,
    "cookie": cookie,
  },
});

The examples use a 110-second client timeout. Most solves finish in a few seconds; the API gives up on a solve after 90 seconds and still answers with JSON.

Health check

GET https://api.nullflare.com/health

{"status":"ok"}

This is an unauthenticated liveness check. It does not validate a client key, report fleet capacity, or use credits.