Docs
Dashboard
Examples / Proxies and CAPTCHAsBeta

CAPTCHA hand-over

Open a form behind a CAPTCHA, see the platform detect it, have a person solve it in the live view, then carry on and submit the form. With captcha: "ask" (the default) nothing is solved automatically. Only on sites you own or may automate.

When to use it: Your own site shows a CAPTCHA, and a person should solve it while the automation waits.

Usessessions with captcha: "ask", attention, onCaptcha / on_captcha, waitForHuman / wait_for_human, captcha events
Needsany plan; no model
Sitea form of your own site with a CAPTCHA (FORM_URL, required). The runner uses its stand-in form with a stand-in reCAPTCHA widget and plays the person
Outputoutput/result.json
LanguagesNode and Python

You take part: It prints the live view link when the CAPTCHA waits: solve it there; the example carries on by itself.

The code

The example as it is in its folder. Both versions do the same job and write the same output/, so one result check covers both.

/** * CAPTCHA hand-over: open a form behind a CAPTCHA, see the platform detect it, have a person solve it in the live * view, then carry on and submit the form. Only on sites you own or may automate (the Acceptable Use Policy). * *   FORM_URL=https://… npx tsx node/index.ts     (BOXLINE_API_KEY; NAME to type into the form's name field) * * The session's `captcha: "ask"` (the default) means: when a CAPTCHA waits for a person, say so and wait; nothing is * solved automatically. Writes output/result.json. */import { mkdirSync, writeFileSync } from "node:fs";import { join } from "node:path";import { Boxline } from "@boxline/sdk";const out = process.env.OUTPUT_DIR ?? "output";const formUrl = process.env.FORM_URL;if (!formUrl) throw new Error("Set FORM_URL to a form of your own site that shows a CAPTCHA");const name = process.env.NAME ?? "Ada Lovelace";const bx = new Boxline();const session = await bx.sessions.create({ captcha: "ask", keepAlive: true, timeout: 600, userMetadata: { example: "captcha-hand-over" } });console.log(`Session: ${session.id}`);let detected = false;const stop = session.onCaptcha(  ({ state, kind, url }) => {    if (state === "detected") {      detected = true;      console.log(`\nA CAPTCHA (${kind}) is waiting for a person on ${url}: solve it in the live view (the link works like a password):\n  ${session.liveUrl}\n`);    } else console.log(`The CAPTCHA (${kind}) was solved.`);  },  { intervalMs: 1000 },);try {  await session.goto(formUrl);  // The platform looks twice, about 2 s apart, before it says a CAPTCHA waits for a person.  const deadline = Date.now() + 30_000;  while (!(await session.refresh()).data.attention && Date.now() < deadline) await new Promise((r) => setTimeout(r, 1000));  const attention = session.data.attention;  if (attention) await session.waitForHuman({ timeoutMs: 5 * 60_000 }); // throws CaptchaTimeoutError if nobody solves it  stop();  await session.fill('input[name="name"]', name);  await session.click('form [type="submit"], form button');  await session.wait(1000);  const { title, content } = await session.content("text");  console.log(`After submitting: "${title}": ${content.replace(/\s+/g, " ").slice(0, 120)}`);  const events = (await session.events({ types: ["captcha"] })).data.map((e) => ({ state: e.data?.state, kind: e.data?.kind, waitedMs: e.data?.waitedMs ?? null }));  mkdirSync(out, { recursive: true });  writeFileSync(join(out, "result.json"), JSON.stringify({ formUrl, attention, detected, events, title, pageSays: content.slice(0, 600) }, null, 2));} finally {  stop();  await session.stop();}

Inputs

Environment variables the example reads:

  • FORM_URL: your form with a CAPTCHA (required).
  • NAME: what to type into its name field (default Ada Lovelace).

Run it

Get the examples with git clone https://github.com/Boxline-dev/examples.git and open this one: cd examples/captcha-hand-over. Put your API key in BOXLINE_API_KEY (and BOXLINE_API_URL for another API), then run either version from the example’s folder. Both write to output/ and stop their sessions when they finish.

# Node 18 or newer, in the example's folderexport BOXLINE_API_KEY=…   # your API keynpm install @boxline/sdk tsxnpx tsx node/index.ts

Then check the result, from the same folder: npx tsx check.ts output. It exits with 0 only when the result is right.

What its check proves

check.ts reads what the example wrote and passes only when the result is right, not merely when the example ran.

The CAPTCHA was detected and cleared (with the time it waited), and the form went through with the answer.

Source

github.com/Boxline-dev/examples/captcha-hand-over on GitHub, with its README.md, check.ts and .env.example. The examples are open source. See all examples.

These docs describe a beta API. Endpoints, fields and SDK methods may change before general availability; breaking changes will be listed in the changelog.