Human in the Loop
Some browser automation workflows require manual intervention. A login page may need multi-factor authentication, a form may require sensitive credentials you do not want to pass to an automation script, or a task may be too complex to fully automate. Human in the Loop lets a human step into a live browser session through Live View to handle what automation cannot, then hand control back to the script.
Human in the Loop works with any Browser Session and uses Live View to give humans access:
- Your automation script navigates to a page that needs human input.
- The script retrieves the Live View URL from the session's target list and shares it with a human operator (for example, by sending it via Slack, email, or displaying it in a user interface).
- The human operator opens the Live View URL and completes the required action (logging in, solving a CAPTCHA, entering sensitive data, etc.).
- The automation script detects that the human is done (for example, by waiting for a navigation event or polling for a page element) and resumes.
A more structured handoff flow where the agent can signal that it needs help and notify a human is coming soon.
This example uses Puppeteer connected to Browser Run via the CDP endpoints. The script navigates to a login page, shares a Live View URL for a human to enter credentials, then continues the automation after login completes.
import puppeteer from "puppeteer-core";
const ACCOUNT_ID = "<your-account-id>";const API_TOKEN = "<your-api-token>";
// Create a browser session via CDPconst response = await fetch( `https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/browser-rendering/devtools/browser?keep_alive=600000&targets=true`, { method: "POST", headers: { Authorization: `Bearer ${API_TOKEN}` }, },);const { webSocketDebuggerUrl, targets } = await response.json();const liveUrl = targets[0].devtoolsFrontendUrl;
// Connect Puppeteer to the sessionconst browser = await puppeteer.connect({ browserWSEndpoint: webSocketDebuggerUrl, headers: { Authorization: `Bearer ${API_TOKEN}` },});
const page = await browser.newPage();await page.goto("https://example.com/login");
// Share the Live View URL with the human operator (for example, send it via Slack, email, or display it in a UI)console.log(`Human input needed. Open this URL: ${liveUrl}`);
// Wait for the human to complete login (5 minute timeout — the script will continue after this period)await page.waitForNavigation({ waitUntil: "networkidle0", timeout: 300000 });
// Login complete, continue automationconst cookies = await page.cookies();console.log("Login complete. Continuing automation...");
await page.goto("https://example.com/dashboard");const content = await page.content();
browser.disconnect();The Live View URL is valid for five minutes from when it was generated. If the URL expires before the human operator opens it, list the targets again to get a fresh URL.
- Authentication flows: Login pages with MFA, SSO, or CAPTCHA that cannot be bypassed programmatically
- Sensitive data entry: Forms requiring credentials or personal information you do not want to pass to an automation script
- Complex interactions: One-off tasks that are too difficult or not worth fully automating, such as configuring a dashboard or approving a workflow
- Verification steps: Confirming an order, reviewing generated content, or approving an action before the script proceeds