diff --git a/src/content/docs/browser-rendering/features/custom-fonts.mdx b/src/content/docs/browser-rendering/features/custom-fonts.mdx index b858a32ac0bf365..c314916c4881c39 100644 --- a/src/content/docs/browser-rendering/features/custom-fonts.mdx +++ b/src/content/docs/browser-rendering/features/custom-fonts.mdx @@ -3,7 +3,7 @@ pcx_content_type: how-to title: Custom fonts description: Learn how to add custom fonts to Browser Rendering for use in screenshots and PDFs. sidebar: - order: 1 + order: 3 --- import { Tabs, TabItem } from "~/components"; diff --git a/src/content/docs/browser-rendering/features/human-in-the-loop.mdx b/src/content/docs/browser-rendering/features/human-in-the-loop.mdx new file mode 100644 index 000000000000000..57c4b4950613d0a --- /dev/null +++ b/src/content/docs/browser-rendering/features/human-in-the-loop.mdx @@ -0,0 +1,80 @@ +--- +pcx_content_type: how-to +title: Human in the Loop +description: Temporarily hand off browser control to a human operator for authentication, sensitive actions, or tasks that are difficult to fully automate. +sidebar: + order: 2 + badge: Beta +--- + +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](/browser-rendering/features/live-view/) to handle what automation cannot, then hand control back to the script. + +## How it works + +Human in the Loop works with any [Browser Session](/browser-rendering/#integration-methods) and uses [Live View](/browser-rendering/features/live-view/) to give humans access: + +1. Your automation script navigates to a page that needs human input. +2. The script retrieves the [Live View](/browser-rendering/features/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). +3. The human operator opens the Live View URL and completes the required action (logging in, solving a CAPTCHA, entering sensitive data, etc.). +4. 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. + +## Example: login with human assistance + +This example uses [Puppeteer](/browser-rendering/puppeteer/) connected to Browser Run via the [CDP](/browser-rendering/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. + +```js +import puppeteer from "puppeteer-core"; + +const ACCOUNT_ID = ""; +const API_TOKEN = ""; + +// Create a browser session via CDP +const 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 session +const 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 automation +const 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. + +## Use cases + +- **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 + +:::note[Bot detection] +Browser Rendering requests are [always identified as bot traffic](/browser-rendering/faq/#will-browser-rendering-be-detected-by-bot-management). Even with a human controlling the session, some third-party services may still block the request. +::: diff --git a/src/content/docs/browser-rendering/features/live-view.mdx b/src/content/docs/browser-rendering/features/live-view.mdx new file mode 100644 index 000000000000000..fde7909f72a11f9 --- /dev/null +++ b/src/content/docs/browser-rendering/features/live-view.mdx @@ -0,0 +1,126 @@ +--- +pcx_content_type: how-to +title: Live View +description: View and interact with remote Browser Run sessions in real time using the hosted DevTools UI or native Chrome DevTools. +sidebar: + order: 1 + badge: Beta +--- + +import { CURL, DashButton } from "~/components"; + +Live View lets you see and interact with a remote Browser Run session in real time. This is useful for debugging automation scripts, monitoring what a browser is doing, or manually stepping in when a task requires human intervention (see [Human in the Loop](/browser-rendering/features/human-in-the-loop/)). + +Live View is available for any [Browser Session](/browser-rendering/#integration-methods), including sessions created with [Puppeteer](/browser-rendering/puppeteer/), [Playwright](/browser-rendering/playwright/), or the [CDP](/browser-rendering/cdp/) endpoints. + +## How to access Live View + +There are three ways to access Live View: through the Cloudflare dashboard, via the hosted user interface (UI) at `live.browser.run`, or using native Chrome DevTools. + +### Cloudflare dashboard + +In the Cloudflare dashboard, go to the **Browser Run** page and select the **Live Sessions** tab. This shows all active browser sessions in your account. Expand a session to see its tabs, then select **Open** to open the Live View for that tab. + + + +### Hosted UI (any browser) + +When you create a session or list targets through the [CDP](/browser-rendering/cdp/) endpoints, the API response includes a `devtoolsFrontendUrl` for each target (tab). Open this URL in any browser to load the DevTools UI hosted at `live.browser.run`, which streams the remote session to your browser. + +The hosted UI supports two viewing modes, controlled by the `mode` parameter in the URL: + +| Mode | URL pattern | Description | +| --- | --- | --- | +| Tab | `https://live.browser.run/ui/view?mode=tab&wss=...` | Standalone page view | +| Inspector | `https://live.browser.run/ui/view?mode=devtools&wss=...` | DevTools inspector panel (Elements, Console, Network, etc.) | + +### Native Chrome DevTools (Chrome only) + +Because Browser Run speaks standard CDP, you can connect Chrome's built-in DevTools directly to a remote session. Replace the `https://live.browser.run/ui/inspector?wss=` prefix in the `devtoolsFrontendUrl` with the `devtools://` protocol: + +```txt +devtools://devtools/bundled/inspector.html?wss=live.browser.run/api/devtools/browser/SESSION_ID/page/TARGET_ID?jwt=... +``` + +Paste this URL into Chrome's address bar to connect native DevTools to the remote browser session. You will get the same DevTools interface you use for local debugging. The `devtools://` protocol is Chrome-only and limited to inspector viewing mode. + +:::caution[URL validity] +The `devtoolsFrontendUrl` is valid for five minutes from when it was generated. If you do not open the URL within this timeframe, list the targets again to get a fresh URL. Once the DevTools connection is established, it remains active as long as the browser session is alive. +::: + +## View a new session + +1. Create a browser session with `targets=true` to include target URLs in the response: + + + +```json +{ + "sessionId": "1909cef7-23e8-4394-bc31-27404bf4348f", + "targets": [ + { + "description": "", + "devtoolsFrontendUrl": "https://live.browser.run/ui/inspector?wss=live.browser.run/api/devtools/browser/1909cef7-.../page/8E598E99...?jwt=...", + "id": "8E598E996530FB09E46A22B8B7754F7F", + "title": "about:blank", + "type": "page", + "url": "about:blank", + "webSocketDebuggerUrl": "wss://live.browser.run/api/devtools/browser/1909cef7-.../page/8E598E99...?jwt=..." + } + ], + "webSocketDebuggerUrl": "wss://api.cloudflare.com/client/v4/accounts/{account_id}/browser-rendering/devtools/browser/1909cef7-..." +} +``` + +2. Copy the `devtoolsFrontendUrl` from `targets[0]` and open it in your browser. You now have a live, interactive view of the remote browser session. + +## View an existing session + +If you have a running session and want to connect to it: + +1. List your active sessions: + + + +2. Using the session ID, list the targets in that session: + + + + + ```json output {8} + [ + { + "id": "110850A800BDB8B593CDDA30676635CF", + "type": "page", + "url": "https://example.com", + "title": "Example Domain", + "description": "", + "devtoolsFrontendUrl": "https://live.browser.run/ui/view?wss=live.browser.run/api/devtools/browser/28d75446-.../page/110850A8...?jwt=...", + "webSocketDebuggerUrl": "wss://live.browser.run/api/devtools/browser/28d75446-.../page/110850A8...?jwt=..." + } + ] + ``` + +3. Copy the `devtoolsFrontendUrl` and open it in your browser.