Skip to content

How to integrate ​

Everything below talks to the container you're already running (see Deployment). There's no SaaS endpoint and no account — requests go to your own host, e.g. http://localhost:3000.

Pick a path ​

There are really only two decisions: do you need a browser, and if so, which one. Pick on what the rest of your job needs, not on which sounds more robust.

CostTLS fingerprintUse when
Via the API~4 HTTP requestsyoursyou're in a language we don't ship an example for
Via HTTP (Node, Python)~4 HTTP requestsyoursyou just need the clearance cookie
Via a browser (Playwright)a full Chrome per sessionChrome's, genuinelythe site needs a browser anyway
Via a browser (Lightpanda)a ~70MB binary per sessionChrome's, via a local proxyyou need a browser at volume
Via Claude——you want an agent to write the integration
Via MCP——you want an agent to solve challenges while it browses

If all you want is a cookie, don't use a browser. The HTTP path is dramatically cheaper — four requests and a few hundred milliseconds — and it's what most integrations should take. Reach for a browser when you were going to drive one regardless: the site is a SPA, needs a login flow, or renders content you can't get from raw HTML.

Between the two browsers, start with Playwright and Chrome. Lightpanda is the same shape at a fraction of the memory, but it needs a re-originating proxy in front of it and has several failure modes that don't look like themselves — its page covers them.

Calling the API ​

Every approach is plain HTTP (plus a WebSocket, for Akamai in the browser flow) against your container:

EndpointWhat it does
GET /hcHealth check — {"status":"ok"}
GET /statsSolve counts and success rates, for your own monitoring
POST /dd/solveSolve a DataDome captcha or interstitial
POST /akamai/solveSolve an Akamai sensor challenge from a URL
WS /akamai/sessionStreaming Akamai session for browser-driven solving
POST /akamai/sbsd/generate-sessionIssue an SBSD ledger for one live document
POST /akamai/pixel/generateProduce the POST Akamai's pixel collector would send
POST /f5/solveSolve an F5/Shape challenge → attested headers for one request

Full contracts: Akamai · DataDome · F5 / Shape · OpenAPI spec. See Via the API for the raw request-by-request flow in curl.

If you're in TypeScript, the SDK gives you typed request and response shapes for these endpoints (types only — you still make the calls yourself).

Authentication ​

There is none, and there's no API key to obtain. The container is licence-gated at startup, not per-request — once it's running, anything that can reach port 3000 can use it.

That's deliberate: the security boundary is the network, not a header. The container is designed to run on a box whose egress you've locked down (see Network posture), reachable only from your own scrapers. Put it on a private subnet or behind firewall rules and you're done.

Why the examples send x-api-key

Scripts in xhrdev/examples thread an optional solver_api_key through as an x-api-key header. That's for the hosted trial box we lend to prospects during an evaluation, which sits behind a reverse proxy that checks the header. Your own deployment ignores it — leave solver_api_key unset and the examples send nothing.

Two rules that decide whether this works ​

Almost every "the solve failed" report comes down to one of these.

1. Submit from the IP you'll browse from ​

Anti-bot vendors bind the clearance cookie to whichever IP submitted it. If the solver submits on your behalf, you get a cookie that's valid for the container and void from your scraper — a fresh 403 on the very next request, which looks exactly like a failed solve.

/dd/solve is built around this: it returns a prepared submission rather than sending one, so you make the request from the address you'll browse from. See why you send the submission.

2. Keep the identity consistent ​

The profile / js_profile you send the solver has to match the headers you actually put on the wire — user agent, sec-ch-ua, platform, language, timezone. These get cross-checked. Changing a user agent in one place and not the other is the single most common way to get a solve rejected, and the error it produces looks nothing like the cause.

Solving is not the same as staying unblocked ​

Worth setting expectations: the solve can succeed and the site can still refuse you afterwards. Clearance cookies get you past the challenge; whether the site then honours the cookie depends on separate signals — chiefly your TLS fingerprint and IP reputation.

If you're solving successfully but still getting blocked:

  • Datacenter IPs are frequently rejected regardless of a valid cookie. Try a residential pool.
  • Non-browser TLS fingerprints are visible to the site even when the cookie is good. This is a different problem from solving, and it's the main reason to use the browser approach despite the cost.

Next ​