← Blog

BLOG

Hermes Remote Browser Not Working: Fixes and Setup

Hermes remote browser not working? Diagnose connection, CDP, and session errors, then wire Hermes agents to a hosted Chromium runtime reliably.

September 24, 20269 min readRemote Browser

# Hermes Remote Browser Not Working: Fixes and Setup

If your Hermes remote browser is not working, the failure is almost always one of four things: the browser endpoint is unreachable, the CDP handshake is rejected, the session died mid-task, or the agent is pointed at a local Chrome that no longer exists. This guide walks through each failure mode, shows how to confirm which one you are hitting, and explains how to wire Hermes to a hosted Chromium runtime so the connection survives restarts, retries, and scale.

The short version: Hermes needs a stable CDP endpoint, not a browser binary on the same machine. When you run Hermes against a remote browser, you separate the agent process from the browser process. That separation is what makes failures diagnosable — and fixable.

Why Hermes remote browser connections fail

Hermes is an agent framework that drives a browser through a control protocol, typically Chrome DevTools Protocol (CDP) or a Playwright/Puppeteer connection layer. When you point it at a remote browser, several things must line up:

  • The endpoint URL must be reachable from wherever the Hermes process runs.
  • The browser must expose a CDP websocket that accepts the connection.
  • The session must stay alive for the duration of the task.
  • The agent's browser tool must be configured to use the remote endpoint, not a bundled local browser.

Most "not working" reports trace back to a mismatch in one of these four. Let's take them in order.

Symptom 1: Connection refused or timeout

If Hermes throws ECONNREFUSED, ETIMEDOUT, or a websocket handshake error, the endpoint is not reachable. Common causes:

  • The browser session was never started, or it already expired.
  • The endpoint host is only reachable from inside a VPC, and your Hermes worker is outside it.
  • A firewall or egress rule blocks the CDP port.
  • You copied a ws:// URL from a dashboard that has since rotated.

Fix: verify reachability before blaming Hermes. From the same host that runs the agent:

curl -sS -o /dev/null -w "%{http_code}\n" https://<your-endpoint>/json/version

A healthy hosted Chromium returns 200 with a JSON body containing webSocketDebuggerUrl. If that call fails, Hermes will fail too — the problem is network or session lifecycle, not the agent.

Symptom 2: CDP handshake rejected

You can reach the endpoint, but the connection drops immediately. This usually means:

  • The session token or API key is missing, expired, or scoped to a different project.
  • You are connecting to the HTTP port instead of the websocket URL.
  • The browser was launched without remote debugging enabled.

Playwright's connectOverCDP is strict about this. If you pass an HTTP endpoint where a websocket is expected, you get an opaque error rather than a clear message. Always use the webSocketDebuggerUrl value, not the base host.

Symptom 3: Session dies mid-task

The connection works, the agent starts, then the browser disappears halfway through. Causes:

  • The session hit an idle timeout because the agent paused on a slow model call.
  • The worker running Hermes was recycled (common on serverless or spot instances).
  • The browser process crashed on a heavy page.

This is the failure mode that local Chrome hides and remote browsers expose. It is also the one that matters most in production, because a task that dies at step 14 of 20 wastes the whole run.

Symptom 4: Hermes is still using local Chrome

Sometimes nothing is broken — Hermes simply never switched to the remote browser. The agent's browser tool defaults to launching a local Chromium. If that binary is missing (common in slim containers), you get a launch error that looks like a remote-browser problem but is not.

Check the agent's browser configuration. If it references a local executable path or chromium.launch(), it is not using your remote endpoint.

Diagnosing the failure in order

Work through this checklist before changing any code:

  1. Confirm the session exists. Open the live viewer for the session and check it is running.
  2. Confirm reachability. Run the curl check above from the agent host.
  3. Confirm the URL type. Use the websocket URL, not the HTTP base.
  4. Confirm auth. Verify the token is present and not expired.
  5. Confirm the agent config. Make sure Hermes is told to connect, not launch.
  6. Confirm session lifetime. Check idle timeout against your longest model call.

If all six pass and it still fails, the issue is usually in how the agent handles reconnects. That is a code problem, and the next section covers it.

Wiring Hermes to a hosted Chromium runtime

The reliable pattern is: create a session via the runtime API, get its CDP websocket URL, and hand that URL to Hermes. The agent never launches a browser; it connects to one that already exists.

Here is a TypeScript example using Playwright's CDP connection, which is the same path Hermes uses under the hood:

import { chromium } from "playwright";

type Session = {
  id: string;
  cdpUrl: string; // webSocketDebuggerUrl from the runtime
};

async function runHermesTask(session: Session) {
  const browser = await chromium.connectOverCDP(session.cdpUrl, {
    timeout: 30_000,
  });

  // Reuse the existing context so cookies and storage persist
  const context = browser.contexts()[0] ?? (await browser.newContext());
  const page = context.pages()[0] ?? (await context.newPage());

  try {
    await page.goto("https://example.com", { waitUntil: "domcontentloaded" });
    // ... hand `page` to your Hermes browser tool here
  } finally {
    // Disconnect without killing the remote browser
    await browser.close();
  }
}

Two details matter here:

  • `connectOverCDP`, not `launch`. This is the difference between using a remote browser and starting a local one.
  • `browser.close()` disconnects; it does not terminate the remote session. That is what you want if the session should outlive the agent run. If you want the session gone, close it through the runtime API instead.

For the full connection surface — profiles, proxies, and session controls — see the documentation.

Local Chrome vs hosted Chromium for Hermes

The table below summarizes why the local setup breaks and what changes when the browser is hosted.

ConcernLocal ChromeHosted Chromium runtime
Browser binaryMust exist on every workerManaged by the runtime
CDP endpointlocalhost, dies with the processStable URL, survives worker restarts
Session lifetimeTied to the agent processIndependent, configurable idle timeout
ScalingOne browser per worker, memory-boundSessions created on demand
DebuggingAttach locally, hard in containersLive viewer + CDP from anywhere
Profile persistenceManual user-data-dirPersistent profiles per session
Proxy / network settingsPer-machine configConfigurable per session
Failure visibilityOpaque crashesSession state and logs

The trade-off is real: a hosted runtime adds a network hop and a dependency. For a one-off script on your laptop, local Chrome is fine. For anything that runs on a schedule, in a container, or across more than one worker, the hosted model removes an entire class of failures.

Production criteria for a Hermes browser runtime

If you are choosing a runtime rather than debugging one, evaluate against these criteria:

  • CDP compatibility. It must expose a standard CDP websocket so Playwright, Puppeteer, and Selenium can all connect. Avoid runtimes that only offer a proprietary SDK.
  • Session isolation. Each agent task should get its own browser context so cookies and storage do not leak between runs.
  • Persistent profiles. For workflows that require login state, profiles must survive across sessions.
  • Live viewer. You need to see what the agent sees when a task fails at step 14.
  • Configurable browser settings. Proxy, locale, timezone, and user-agent should be settable per session.
  • Usage controls. You should be able to cap session duration and concurrency to control cost. Current limits and rates are on the pricing page.
  • Reconnect semantics. The runtime should let you reconnect to a live session after a worker restart.

If a runtime cannot answer these, it will not survive production traffic.

Common Hermes-specific pitfalls

Beyond the four failure modes, a few Hermes-specific issues show up repeatedly:

The agent closes the browser after every step. Some browser tools call browser.close() at the end of each action. Against a remote session, that tears down the connection and forces a reconnect. Configure the tool to keep the connection open for the task duration.

Model latency exceeds the idle timeout. A slow LLM call can leave the browser idle long enough to be reaped. Either raise the idle timeout or send a lightweight keepalive (a page.title() call) between steps.

Concurrent tasks share one session. If two Hermes tasks connect to the same CDP endpoint, they will fight over tabs and navigation state. Create one session per task. This is the single most common cause of "it works alone but breaks under load."

Retries reuse a dead session. When a task fails and retries, it must create a fresh session or verify the old one is still alive. Reusing a stale cdpUrl produces exactly the connection-refused error from Symptom 1.

The agent assumes a visible browser. Headless and headed sessions behave differently for some sites. If a workflow depends on rendering, confirm the session mode matches.

When to move off local Chrome entirely

The decision is straightforward. Move to a hosted runtime when any of these are true:

  • Your agent runs in a container, serverless function, or CI job.
  • You need more than a handful of concurrent sessions.
  • Tasks must survive worker restarts.
  • You need to debug failures after the fact.
  • You are managing proxies or profiles across machines.

Stay local when you are prototyping a single workflow on a machine you control and do not care about persistence.

For a broader look at how the runtime layer fits into agent architecture, see Remote Browser for AI Agents. If you want to understand the connection model without installing anything, Remote Browser Online covers the browser-as-a-service path.

A minimal recovery procedure

When Hermes remote browser is not working and you need it back fast, run this sequence:

  1. Kill the current session and create a new one.
  2. Copy the new webSocketDebuggerUrl.
  3. Verify it with curl from the agent host.
  4. Update the agent's browser config to the new URL.
  5. Run a single-step task (navigate + read title) before the full workflow.
  6. If the single step passes, the full task will too — if it fails, the problem is in the agent's step logic, not the connection.

This isolates connection problems from task problems, which is the fastest way to stop guessing.

Summary

A Hermes remote browser that is not working is usually a connection, auth, lifetime, or configuration problem — not a Hermes bug. The fix is to stop launching browsers from inside the agent and start connecting to a hosted Chromium session over CDP. That gives you a stable endpoint, independent session lifetime, a live viewer for debugging, and the ability to scale past one worker.

Start by confirming reachability with a single curl against /json/version. If that passes, the rest is configuration. If it fails, you have found your problem — and it is not in your agent code.

For connection details, session controls, and the full API surface, see the documentation. For current session limits and rates, check pricing.