Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions browsers/telemetry/categories.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,20 @@ A visible captcha challenge can require multiple solver tasks. When the identifi

Challenge results are currently emitted for visible reCAPTCHA v2, hCaptcha, and press-and-hold challenges. Other captcha types can emit task events without a challenge result. Telemetry delivery is best-effort and isn't ordered: a start can arrive after its result, and any event can be absent. When you need a challenge-level outcome, wait for a bounded interval and fall back to available task results and the current page state.

What each `captcha_type` emits today:

| `captcha_type` | Task events | `captcha_challenge_result` | `challenge_id` on task events |
| --- | --- | --- | --- |
| `hcaptcha` | Yes | Yes | Yes |
| `press_and_hold` | Yes | Yes | Yes |
| `recaptcha_v2` | Yes | Yes | Can be absent |
| `turnstile` | Yes | No | Can be absent |
| `geetest` | Yes | No | Can be absent |
| `recaptcha_v3` | Yes | No | Can be absent |
| `other` | Yes | No | Can be absent |

Challenge results for `recaptcha_v2` and `hcaptcha` report `solved` or `abandoned`. `failure` and `timeout` are reported for `press_and_hold`, whose solver has an explicit attempt budget.

Task events carry a `task_id`, but not all of them carry a `challenge_id`. Kernel sets `challenge_id` from tracking the challenge widget in the page - the same tracking that produces `captcha_challenge_result` - so a task the automatic solver runs without it reports a `task_id` only. Those task events can't be joined to a challenge result for the same page, even when one is emitted. Pair a start with its result on `task_id`, and use `challenge_id` for grouping only when it's there.

Use each result event's `duration_ms` as the authoritative duration rather than calculating it from event timestamps. Challenge duration covers every solver attempt from when the challenge appeared until its terminal outcome.
Expand Down
2 changes: 2 additions & 0 deletions browsers/telemetry/pausing-for-captcha-solves.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,8 @@ Durations come straight from each event's `duration_ms`, which is authoritative;
- **Challenge results aren't emitted for every widget type.** Turnstile, for instance, reports task events only, so the task-plus-page path is the one that runs there.
- **One episode at a time.** The gate resets after each verdict; overlapping visible challenges from the same provider aren't split apart, and the telemetry docs note Kernel's own event model can't always attribute a result in that case either.
- **The page probe is best-effort.** It reads the DOM for known widget markers and a response token. A site that renders its challenge somewhere those selectors miss won't be held past the logged message alone.
- **GeeTest has no selector either.** The solver reports `geetest` task events, but `PROBE`'s `groups` has no GeeTest entry and `tokenPresent` checks no GeeTest field, so `widgets` never reports one and the agent proceeds as soon as the task settles, even while the challenge is still open. Add a selector for your target's GeeTest integration if you need it to hold.
- **hCaptcha coverage depends on your organization's configuration.** When the hCaptcha solver isn't enabled for your org, hCaptcha pages produce no captcha events and the gate falls through to the page probe.
- **Press-and-hold has no selector at all.** It emits `captcha_challenge_result` telemetry like reCAPTCHA and hCaptcha, but `PROBE`'s `groups` has no entry for it, so `widgets` never reports one -- the tool-call handler treats that as clear and lets the agent proceed even while the challenge is still open. Add a selector for your target's specific implementation if you need it to actually hold.
- **A reload within `TASK_SETTLE_MS` of the last verdict can still be missed.** `settledAt` treats an ID as fresh again once that window passes, so a genuinely new outcome for a reused `challenge_id` eventually gets through -- but if the reload happens sooner than that, its result is indistinguishable from a stale duplicate and gets dropped.

Expand Down
Loading