Headless and headful
headless takes the literal string true on /connect and a boolean on
POST /api/browser/create. It defaults to false. A browser with a window is
what you get unless you ask otherwise, and it is the mode to use for any site
that scores its traffic.
Headful looks like Chrome because it renders like Chrome
Section titled “Headful looks like Chrome because it renders like Chrome”A headful session runs Chromium with a real window on a display. The page is laid out, painted and composited into that window the same way desktop Chrome does it. Everything that depends on the page actually being drawn behaves like a real machine: window geometry, frame timing, compositing, focus and visibility.
Headless Chromium skips the window and the display. The fingerprint is the same
in both modes, since the user agent, fonts, canvas and WebGL come from the same
profile and navigator.webdriver is false either way. What headless changes is
how the browser runs, and that shows up in many places, most of them below
anything a JavaScript property check would catch. A few examples:
- No window frame. Desktop Chrome draws a frame around the page, so the
outer window is larger than the viewport and a headful session reports an
outerWidthlarger than itsinnerWidth. Headless draws no frame and reports the two as equal. - Rendering and frame timing. Nothing is painted to a screen, so animation frames, paint timing and compositing do not follow the cadence of a displayed page.
- Window, focus and visibility state that no desktop session produces.
A site that scores any of these treats the visit as automation before your code
has run a single action. The IP, the proxy and the fingerprint are all fine, and
the page still comes back as a block or a challenge. The fix is to stop sending
headless=true.
Watching a headful session live is a convenience on top. It is not the reason to run one.
Headless
Section titled “Headless”curl -G "https://browser.rayobyte.com/connect" \ --data-urlencode "os=windows" \ --data-urlencode "headless=true" \ -H "x-api-key: rb_live_YOUR_KEY"Anything other than the exact string true is read as false. headless=1 and
headless=True both give you a headful browser.
Choose it when the target is not scoring the browser: your own staging site, a CI suite, an endpoint you already reach on the first try.
A headless session asked for vnc=true still returns an x-vnc-url, but there
is no window for the viewer to show.
Headful, with the live view
Section titled “Headful, with the live view”A headful browser renders into a virtual display. Add vnc=true and the
response carries a URL that streams that display to you:
curl -i -G "https://browser.rayobyte.com/connect" \ --data-urlencode "os=windows" \ --data-urlencode "vnc=true" \ -H "x-api-key: rb_live_YOUR_KEY"x-vnc-url: https://sb-02.browser.rayobyte.com/vnc/vnc.html?path=ws%3Ftoken%3Dbr_5d4d8610784e2a91&autoconnect=true&resize=scaleOpen it in a tab. The view is there to show you what the browser is doing, not to hand you a machine to click around in.
With the SDKs:
ws_url = client.connect_url(os="windows", vnc=True, proxy=PROXY)print(client.last_vnc_url)const wsUrl = await client.connectUrl({ os: 'windows', vnc: true, proxy: PROXY });console.log(client.vncUrl);x-vnc-url is sent only when vnc=true was requested and the browser came up
with a viewer. Read it with .get() rather than indexing, or a browser that
started without one raises a KeyError in the middle of an otherwise fine
session.
Which to use
Section titled “Which to use”| Mode | Use |
|---|---|
| Headful (default) | Anything that has to look like a person. Scraping, agents, account work |
Headful plus vnc=true |
Working out why a site is behaving differently than you expect |
| Headless | Your own sites, CI, targets that do not challenge you |
Fingerprint spoofing is identical in both modes. Headless changes how the page is rendered, and that is what sites that check for it detect.
Was this page helpful?
Thanks — that helps us fix it.