Challenges
Hosted browsers handle slider and checkbox challenges by themselves. The challenge service, off unless you turn it on, takes the ones they can't.
Slider challenges
Some sites answer with a slide-to-verify challenge: a handle to drag to the end of a bar, or a puzzle piece to drag into its gap. A hosted browser handles these for you, in any tab and inside frames. It is on by default; pass solveSliders: false when your script deals with them itself.
- What it does. A plain slider is dragged to the end. A puzzle is dragged until the piece sits in its gap: the browser finds the gap in the puzzle image, then checks where the piece actually went and corrects. The drag is a pressed, human-paced mouse movement, not a jump.
- When it holds back. If it cannot find the gap with confidence, it leaves the puzzle alone rather than guess, because a wrong drag can count against the session. It tries at most three times per page, and it waits while someone controls the session from the live view or during a hand-off.
- What you see. Every attempt is a
sliderevent in the session's event timeline, with whether the challenge went away afterwards (passed) or not (failed), or why a puzzle was left alone (skipped). - Only challenges are touched: a slider counts as one when the page or the widget around it says so (a captcha or verification check). Range inputs, carousels and price filters are left alone. Your script's own mouse input and a drag in progress can interleave, so pause clicks while a challenge is on screen, or turn the option off.
Checkbox challenges
Some sites ask you to tick a “verify you are human” box first. A hosted browser clicks it for you, in any tab and inside frames, including widgets that hide the box from page scripts. This is a separate option from sliders, also on by default; pass solveCheckboxes: false to handle these boxes yourself.
- Which boxes. Only a checkbox whose own wording says it is a human check (human, robot, captcha, verify you are…). A “remember me” or “I agree to the terms” box is never clicked, whatever else the page says.
- The click. A human-paced pointer movement to the box, a short pause, and a press held as long as a person's click. If the box opens a slider next, the slider is handled as a slider.
- What you see. Every attempt is a
checkboxevent in the session's event timeline:passedwhen the box went away or was ticked,failedwhen it was still waiting. At most three attempts per page, and none while someone controls the session from the live view or during a hand-off.
Challenge service
For sites that keep challenging after the free slider and checkbox actions, a hosted browser can hand the harder challenges to a solving service. It is off unless you ask for it: pass challengeService: true to let it pick by itself, or an object to choose what it may do. It uses your own solving-service key, or ours (billed per solved challenge).
Choosing which challenges it handles
You never tell it which widget or which vendor a site uses. The hosted browser recognises each challenge on the page by itself, from its markup, its frames and how it behaves, and sorts it into one of five categories. You choose categories, not widgets.
| Category | What counts as one | In auto |
|---|---|---|
token | A widget that hands the page a token: an “I'm not a robot” box that turns into a picture puzzle, an invisible widget whose puzzle comes up, an interactive “verify you are human” check that stays unanswered. | Yes |
clearance | A full-page “checking your browser” wait that does not clear by itself. | Yes |
block-page | A site's block page with a puzzle or a device check. | Yes |
image | A distorted-text code next to a text box, and a jigsaw whose gap the browser could not place itself. | Yes |
score | An invisible score check the page runs itself. | No: list it yourself |
- Auto-select.
challengeService: true, or an object withoutcategories(or withcategories: "auto"): every challenge it recognises intoken,clearance,block-pageandimageis handled, on every site.scoreis left out because the browser already earns its own score token: answering it from elsewhere costs a solve on every call, so it is only worth it for a site that rejects your sessions' scores. - Pick categories.
categories: ["token", "image"]handles only those. A challenge of another category is still reported in the timeline (ascategory_off), never paid for. - Pick sites.
sites: ["shop.example"]limits it to those hosts and their subdomains; elsewhere nothing is reported or asked. Combine it withcategoriesfor “this kind of challenge on that site”. - Not sure what a site uses? Run it once with
mode: "report": nothing is asked or paid for, and the timeline lists every challenge the pages showed aschallenge.detectedwith itscategoryand whether it can be solved. Then turn on exactly those categories for that site.
// In the body of POST /api/v1/browsers, or in the SDK's launch options (cloud: true)
// Auto-select: every challenge it recognises (all categories but score), on every site
challengeService: true
// Only widgets that hand out a token, only on one site, at most EUR 0.20 per session
challengeService: { categories: ["token"], sites: ["shop.example"], maxSpendEur: 0.2 }
// Only full-page waits and block pages, with your own solving-service key
challengeService: { categories: ["clearance", "block-page"], key: "own" }
// Auto-select plus the score check, on one site
challengeService: { categories: ["token", "clearance", "block-page", "image", "score"], sites: ["shop.example"] }
// First find out what a site uses: report only, nothing asked or paid for
challengeService: { mode: "report" }All fields
| Field | Type | Default | Meaning |
|---|---|---|---|
categories | "auto" or a list of token, score, clearance, block-page, image | "auto" | Which kinds of challenge may be answered. auto is all but score. |
sites | list of hostnames | every site | Only on these hosts and their subdomains (at most 50). |
key | "own" or "managed" | your stored key if you have one, otherwise ours | Whose solving-service key: yours, or ours (billed per solved challenge). |
apiKey | string | none | Your solving-service key for this session only (stored encrypted, never shown again). Implies key: "own". |
mode | "solve" or "report" | "solve" | report only recognises and reports; nothing is asked or paid for, and no key is needed. |
maxSolves | whole number, 1 to 100 | 10 | Asks per session; the asking stops at this many. |
maxSpendEur | number, 0.01 to 100 | 0.50 | What a session may spend on solves (on our key, what you pay); the asking stops there. |
How it works
- Free first. The slider and checkbox actions always go first. The service is asked only when a challenge is still there after its fair chance: a picture puzzle came up, an invisible widget opened its puzzle, a widget stayed unanswered for about 15 to 25 seconds, a full-page wait did not clear in about 20 seconds, or the page is a block page or a text code.
- How the answer goes in. The way the page expects it: a token into the widget's response field and its callback, a cookie for the site and a reload, a code typed into its box, a jigsaw dragged into place. Then it checks that the challenge is gone, like the free actions.
- The same IP. Full-page waits and block pages must be solved from the IP that uses the answer: the service solves them through your session's own exit IP, over a short-lived, single-use connection. A token a site rejects is asked for once more the same way.
- Your key or ours.
key: "own"uses your solving-service key: store it once in the dashboard (Settings), or passapiKeywith the request. It is stored encrypted, never shown again and never reaches the browser; you pay the service directly.key: "managed"uses ours: each solved challenge is billed from your hosted balance at the service's own price × 1.5, failed attempts free. Leavekeyout to use your stored key if you have one, ours otherwise. - Limits. At most 2 asks per challenge per page. Per session,
maxSolves(default 10, at most 100) andmaxSpendEur(default €0.50): the asking stops at either. On our key, a monthly cap per account (set it in the dashboard, at most €25). A wrong key or an empty balance at the service stops the asking for that session. - What you see.
challenge.detectedonce per challenge per page, andchallenge.servicefor every ask (solved,failedorskipped, with the reason and the service's cost) in the event timeline;challenges(whose key, how many asks, what our key's solves cost) on the session. In an agent run, the agent waits while the service works on a page. - Some widgets are seen but not solved: their answer cannot be put back into a page in a general way. They are reported with
solvable: falseand never paid for. The page address and the challenge's details go to the solving service.
What happens with each kind
| On the page | Category | The service is asked for | How the answer goes in |
|---|---|---|---|
| An “I'm not a robot” box whose click opened a picture puzzle | token | A token for that widget | Into the widget's response field, and the page's callback is called with it |
| An invisible widget whose picture puzzle came up | token | A token for that widget | The same |
| An interactive “verify you are human” check that stays unanswered | token | A token for that widget | The same |
| A distorted-text code next to a text box | image | The text in the picture | Typed into the box, key by key, after a click into it |
| A jigsaw slider the browser cannot place itself (for example one with a decoy hole) | image | Where the gap is | The browser drags the piece there, checking where it actually went |
| A full-page “checking your browser” wait that does not clear | clearance | A clearance cookie, solved through your session's exit IP | Set for the site, then the page reloads |
| A block page with a puzzle or a device check | block-page | A cookie, solved through your session's exit IP | Set for the site, then the page reloads |
An invisible score check the page runs itself (only with score listed) | score | A score token for the page's own action | Handed to the page's own call for a token |
The free actions still come first: a plain slider is dragged, a jigsaw whose gap the browser can find is placed, and a box that ticks on a click is clicked, all without asking the service. In the widget, the box itself can stay unticked after a token went in: the page reads the response field and the callback, not the box.
From the SDKs
SDK 0.38.0 or newer takes the option on a cloud launch (Python: challenge_service, which also accepts max_solves, max_spend_eur and api_key). The timeline says what happened; its last events arrive a few seconds after the session ends.
import { Cloud, launch } from "clearcote";
const browser = await launch({
cloud: true,
challengeService: { categories: ["token", "image"], sites: ["shop.example"], maxSpendEur: 0.2 },
});
const page = await browser.newPage();
await page.goto("https://shop.example/signup");
// ... your script: challenges the free actions cannot clear are answered for you
const id = browser.cloudSession.id;
await browser.close();
const { events } = await new Cloud().browsers.events(id);
for (const e of events) if (e.type.startsWith("challenge.")) console.log(e.type, e.data);
// challenge.detected { category: "token", solvable: true }
// challenge.service { category: "token", outcome: "solved", applied: "callback", attempt: 1, ms: 12725, costUsd: 0.00013 }from clearcote import Cloud, launch
browser = launch(cloud=True, challenge_service={"categories": ["token", "image"], "sites": ["shop.example"], "max_spend_eur": 0.2})
page = browser.new_page()
page.goto("https://shop.example/signup")
session_id = browser.cloud_session["id"]
browser.close()
for e in Cloud().browsers.events(session_id)["events"]:
if e["type"].startswith("challenge."):
print(e["type"], e["data"])