Skip to content

ref(browser): read browser details over CDP and ask /json/version only for url: - #651

Merged
route merged 4 commits into
mainfrom
fix/remote-user-agent
Oct 18, 2026
Merged

route merged 4 commits into
mainfrom
fix/remote-user-agent

Conversation

@route

@route route commented Oct 18, 2026

Copy link
Copy Markdown
Member

What

Ferrum reads browser details (user agent, versions) over CDP with Browser.getVersion for every browser, local or remote. /json/version is only asked when url: is given, to find the websocket url.

Why

  • browserless v2 leaves User-Agent out of /json/version, so headers.add sent Network.setUserAgentOverride with a nil user agent and Chrome answered Invalid parameters (Adding Header using browserless 2 / empty user agent cuprite#300).
  • ws_url: and local launches already know the websocket url, so the HTTP call only added a failure point: a service without an HTTP endpoint couldn't be used with ws_url: at all.
  • When /json/version fails, NoWebSocketUrlError said nothing about why. A missing token, a full service and a wrong url all looked the same.

Changes

  • CDP for browser details. Browser#start sets default_user_agent from Browser.getVersion. Process asks /json/version only for url:, and the version parsing is gone from it.
  • Removed: Browser::Process#default_user_agent, #browser_version, #protocol_version, #v8_version and #webkit_version. Use Browser#default_user_agent and Browser#version.
  • Error status. NoWebSocketUrlError names the HTTP status, e.g. `/json/version` there answered 429 Too Many Requests, and exposes it as #status.
  • Driver. ws_url: clients no longer leave a pending Chrome behind, so the driver claims pending Chromes by id only: / always starts a new one, and the query matching and taken-id fallback are gone.
  • DESIGN. Explains why reset can't isolate tests on a browser that came up with a startup window, as browserless's does, and why Ferrum won't work around it.

Testing

  • New specs: headers work when /json/version has no User-Agent, ws_url: works through a proxy that hangs up on /json/version, and the 401 message names the status. Each fails without its change.
  • Full suite locally: 632 examples, 0 failures.
  • Go tests with -race.
  • New Ferrum against the new driver: url: and ws_url: each start exactly one Chrome, and headers work.

route added 4 commits October 18, 2026 08:43
…y for the url: websocket

Browser data came from /json/version over HTTP, which ws_url: and local launches didn't need and which some services answer without a User-Agent (browserless v2), so headers.add sent a nil user agent and failed with Invalid parameters (rubycdp/cuprite#300). Browser#start now reads it from Browser.getVersion for every browser, and /json/version is only used to find the websocket url for url:. The version readers on Browser::Process are removed in favor of Browser#version.
…nts don't ask /json/version

Ferrum used to call /json/version before connecting with ws_url:, so / claimed a pending Chrome with the same query and /devtools/browser/<id> fell back the same way when / took its id. Ferrum now connects to / directly, so / always starts a new Chrome and a pending one is claimed only by its id.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant