ScreenshotNeo

BlogHow-to

How to Reduce Proxy Usage with Browser Reconnects

Reconnect to a live browser to resume its page and state after a brief interruption. Learn when that can avoid repeated proxy requests, how to implement it, and how to measure the result.

By the ScreenshotNeo team4 October 20269 min read

Short answer: reconnect to the same still-running remote browser after a brief client interruption. If resuming lets your workflow continue without repeating navigation, login, or page setup, it may avoid some requests through your proxy. Reconnects do not guarantee lower proxy usage: pages can continue making network requests, and reconnecting alone does not prove any proxy traffic was saved. Measure your own workload before claiming savings.

This guide uses Browserless as a concrete example because its documentation describes browser reconnects. The workflow applies only when your browser service and session method support reconnecting.

1. Understand what a reconnect can save

A reconnect is a handoff to a browser process that is still alive. The next client attaches to that process, so it can continue with the same open page, cookies, localStorage, and in-memory page state. That can avoid repeating work such as loading a page or following an authentication path after a short interruption. [Browserless reconnect guide](https://docs.browserless.io/examples/reconnect)

The possible proxy savings come from the work you do not repeat. A reconnect does not suppress new requests made by the page, guarantee that the next action uses fewer proxy requests, or change how your proxy provider counts traffic. It may also add browser waiting time or session charges.

Workflow situation Likely fit Why
Client restarts after a short interruption; same open page is needed Reconnect Resume the live browser instead of navigating and setting it up again.
Only cookies or localStorage need to survive a later run Persisted state Durable storage may survive a browser restart without keeping a process waiting.
Next task needs a different page and no prior state Fresh session There may be no repeated setup or navigation to avoid.
Long gap beyond the reconnect window Persisted state or fresh session A reconnect only works while the live process remains available.

Browserless distinguishes a live process handoff from persisted state: cookies, localStorage, and cache may persist across browser restarts, while open pages and in-memory state require the original process to remain alive. Its persisting state documentation describes the distinction.

2. Choose the session method and client

There are two documented Browserless patterns. Do not assume their APIs or client support are interchangeable.

  • BAP reconnect: call reconnect() while connected. It returns endpoints for later connections. Browserless documents CDP endpoints for Puppeteer or Playwright, as well as BAP and BrowserQL options. The endpoints omit the API token; add authentication on each subsequent connection. See BAP session reconnects.
  • Standard Sessions: the separately documented Browserless.reconnect CDP workflow relies on Puppeteer’s browser.disconnect(). Browserless documents this pattern as Puppeteer-only because Playwright does not expose that disconnect method. See Standard Sessions.

The examples below use Browserless’s documented BAP endpoint and TypeScript SDK. Use the current endpoint and account limits shown in your own Browserless documentation/account; service limits can vary by plan and change.

3. Implement a bounded reconnect with BAP

Install the SDK, set your API token in the environment, and run the script. The first process opens a page, requests a short reconnect window, and prints the returned session endpoint. A later process can attach to that endpoint before the window expires.

npm install @browserless.io/bap-ts
import Browserless from "@browserless.io/bap-ts";

const TOKEN = process.env.BROWSERLESS_TOKEN;
if (!TOKEN) throw new Error("Set BROWSERLESS_TOKEN first");

const browser = Browserless.connect({
  browserWSEndpoint: "wss://production-sfo.browserless.io/chromium/bql",
  token: TOKEN,
});

try {
  const page = await browser.newPage();
  await page.goto("https://example.com/dashboard", {
    waitUntil: "domContentLoaded",
  });

  // Keep the browser available for a short handoff window.
  const session = await page.reconnect({ timeout: 30_000 });

  // Treat the endpoint as sensitive session data. Pass it securely to the
  // process that will resume the browser; do not log a token-bearing URL.
  console.log(JSON.stringify({ browserWSEndpoint: session.browserWSEndpoint }));
} finally {
  // The reconnect grace period survives this client closing after a
  // successful reconnect(); before that call, close() cleans up the session.
  await browser.close();
}

For the next client, provide the endpoint produced by the first process as RESUME_ENDPOINT. The code adds the token separately, lists the existing pages, and closes the session when finished.

import Browserless from "@browserless.io/bap-ts";

const TOKEN = process.env.BROWSERLESS_TOKEN;
const endpoint = process.env.RESUME_ENDPOINT;
if (!TOKEN || !endpoint) {
  throw new Error("Set BROWSERLESS_TOKEN and RESUME_ENDPOINT");
}

const resumed = Browserless.connect({
  browserWSEndpoint: endpoint,
  token: TOKEN,
});

try {
  const pages = await resumed.pages();
  if (pages.length === 0) throw new Error("Resumed browser has no open pages");
  console.log("Resumed URL:", await pages[0].url());
  // Continue the task here using the same live browser and page state.
} finally {
  await resumed.close();
}

In production, hand off the endpoint through a protected queue or secret store, add a deadline to the receiving job, and make cleanup run on success and failure. Returned endpoints and tokens are credentials for a live session.

4. Alternative reconnect examples: cURL and Python

Browserless also documents a BrowserQL-over-HTTP flow. It starts a session with a navigation and reconnect mutation, then sends a second request to the returned browserQLEndpoint. The following commands show the documented shape; replace the token and preserve the endpoint returned by the first response for the follow-up request.

curl -X POST \
  "https://production-sfo.browserless.io/stealth/bql?token=YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "mutation StartSession { goto(url: \"https://example.com\", waitUntil: domContentLoaded) { status } reconnect(timeout: 30000) { browserQLEndpoint browserWSEndpoint } }",
    "variables": {},
    "operationName": "StartSession"
  }'

Use the returned browserQLEndpoint in the second command, adding your token for authentication:

curl -X POST \
  "RETURNED_BROWSERQL_ENDPOINT?token=YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "mutation ContinueSession { html { html } }",
    "variables": {},
    "operationName": "ContinueSession"
  }'

The Python version uses the same documented BrowserQL request pattern. Install requests; this script opens the page, requests reconnect, then uses the returned endpoint to retrieve the page HTML.

import os
import requests

TOKEN = os.environ["BROWSERLESS_TOKEN"]
base = "https://production-sfo.browserless.io/stealth/bql"
start_query = '''mutation StartSession {
  goto(url: "https://example.com", waitUntil: domContentLoaded) { status }
  reconnect(timeout: 30000) { browserQLEndpoint }
}'''

start = requests.post(
    f"{base}?token={TOKEN}",
    json={"query": start_query, "variables": {}, "operationName": "StartSession"},
    timeout=90,
)
start.raise_for_status()
data = start.json()
if "errors" in data:
    raise RuntimeError(data["errors"])
endpoint = data["data"]["reconnect"]["browserQLEndpoint"]

continued = requests.post(
    f"{endpoint}?token={TOKEN}",
    json={
        "query": "mutation ContinueSession { html { html } }",
        "variables": {},
        "operationName": "ContinueSession",
    },
    timeout=90,
)
continued.raise_for_status()
result = continued.json()
if "errors" in result:
    raise RuntimeError(result["errors"])
print(result["data"]["html"]["html"][:500])

These HTTP requests illustrate a single client making a follow-up request to the same browser session. For an actual client handoff, securely pass the returned endpoint and authenticate the receiving client as required. Do not write token-bearing endpoints to application logs.

5. Set the timeout and lifecycle deliberately

  1. Estimate the interruption window. Choose the shortest grace period that allows the next worker to start and attach. Browserless BAP defaults to 30,000 milliseconds when no timeout is supplied.
  2. Stay within account limits. A timeout above the plan’s maximum session duration can fail. The session’s absolute maximum duration also bounds the remaining reconnect window; reconnecting repeatedly does not extend that original deadline.
  3. Reconnect only when state matters. If the next task needs only durable cookies or storage, consider persisted state rather than an idle live process.
  4. Close as soon as work ends. Browserless says a browser waiting for reconnection still bills and occupies a concurrency slot. Bound the wait and close the session on completion or unrecoverable error. See its browser session lifecycle guide.
  5. Handle expired sessions. If the handoff window expires, start a new browser and restore only the durable state your workflow needs. Do not assume the old open page or in-memory inputs remain.

Exact prices, plan caps, maximum session durations, and included features can change. Check the current product documentation and your account before relying on any particular limit.

6. Measure whether proxy use actually fell

There is no documented general percentage reduction from reconnects. Compare the same workload with and without reconnects and count the proxy traffic directly. A useful experiment keeps the target URLs, job volume, proxy configuration, browser actions, and timeout policy the same.

  1. Record a fresh-session baseline: proxy requests or provider charges, repeated navigations, authentication requests, browser session duration, and failures.
  2. Run the reconnect version with a bounded wait. Record the same fields plus reconnect success rate and time spent waiting.
  3. Compare total proxy charges and total browser/session cost, not just requests avoided on a single resumed page.
  4. Repeat enough runs to account for variable page resources, retries, and failed reconnects. Report the workload and observation period alongside any savings figure.

Separate requests that would have been repeated from requests the live page makes while idle or after reconnect. A page may continue fetching scripts, images, analytics, or application data during the handoff. The reconnect itself is not evidence that these requests stopped.

7. Troubleshooting

Symptom Likely cause Fix
Reconnect times out or returns a timeout-limit error Requested window exceeds the plan’s maximum, or the original session deadline is near. Use a shorter timeout and check the plan’s maximum session duration. Reconnect cannot reset the original session clock.
401 Unauthorized on the resumed connection The returned endpoint omits the API token. Supply the token again using the documented client authentication method. Keep token-bearing URLs out of logs.
Connection fails after a long pause The reconnect grace period expired or the browser reached its maximum duration. Attach sooner, shorten the handoff process, or start a fresh browser and restore persisted state.
Open page is missing but cookies remain The browser process ended and only persistent user data survived. Use a live reconnect when the exact page and in-memory state matter; use persisted state only for data designed to survive a restart.
Playwright cannot use the Standard Sessions recipe That specific pattern depends on Puppeteer’s browser.disconnect(). Use the Browserless BAP reconnect flow that documents Playwright/CDP endpoints, or use the documented client method that matches your runtime.
Proxy request count did not drop The resumed page still fetched resources, or the workflow did not repeat meaningful navigation/setup. Inspect request logs and compare equivalent runs. Reconnects only have a chance to avoid the repeated work your workflow would otherwise perform.
Concurrency is unexpectedly exhausted Disconnected browsers are still waiting in their reconnect windows. Reduce the grace period, ensure receivers always attach or abandon cleanly, and close sessions promptly.

8. Or skip the browser setup

If the deliverable is a clean screenshot rather than a live browser session, ScreenshotNeo provides a website screenshot API and MCP server. One GET request captures a URL as PNG, JPEG, WebP, or PDF; see the API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
  • Cookie banners are accepted like a visitor; 60+ known consent platforms, newsletter popups, and chat widgets are removed before the shot. Each step can be turned off.
  • Bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing; response headers report the page verdict and billing status.
  • An MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients.
  • The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Every feature is on every plan.

Create a free ScreenshotNeo account and get 1,000 screenshots a month with no card.

9. FAQ

Does reconnecting guarantee fewer proxy requests?

No. It can avoid requests only when it prevents work your workflow would otherwise repeat. Confirm the change from proxy logs or provider charges.

Can I keep extending the browser by reconnecting repeatedly?

No. Reconnects do not extend the session’s original maximum duration, and the grace period remains bounded by the time left in that session.

Should I reconnect or save browser state?

Reconnect when the next task needs the same live page or in-memory state. Persist durable cookies or storage when a browser restart is acceptable.

Does a disconnected browser use a concurrency slot?

Yes, while it waits for reconnection. Keep the wait bounded and close the browser when the work is done.

Sources