Agent.Connect SDK
Automatically retry failed Playwright navigations using real mobile proxies from Aluvia.
Overview
When you run Playwright for automation, scraping, or testing, page navigations can fail because of unstable networks, blocked IPs, or temporary connection issues. By default, Playwright throws an error like ETIMEDOUT, net::ERR_CONNECTION_RESET, or TimeoutError and stops running unless you handle it manually.
This SDK solves that problem automatically. It catches retryable navigation errors, fetches a proxy (from your Aluvia account or your own proxy provider), and retries the same navigation.
Unlike a full-time proxy setup, this SDK only uses a proxy when a navigation fails. Your sessions start on a direct connection and fall back to a proxy only when needed, keeping your Playwright scripts more stable without extra configuration.
More examples and documentation are available on GitHub
Installation
You can find this package on npm
Install the package using your preferred Node.js package manager:
# npm
npm install @aluvia-connect/agent-connect
# yarn
yarn add @aluvia-connect/agent-connect
# pnpm
pnpm add @aluvia-connect/agent-connect
You also need Playwright installed in your project if it isn’t already:
npm init playwright@latest
Token Setup
The SDK needs a valid Aluvia token key to fetch proxies when a retry is triggered. You can find your token on your Aluvia account's credentials page.
Set your token key in a .env file:
ALUVIA_TOKEN=your_aluvia_token
Quick Start Example
import { chromium } from "playwright";
import { agentConnect, startDynamicProxy } from "@aluvia-connect/agent-connect";
// Start local proxy-chain server (random free port)
const dyn = await startDynamicProxy();
// Launch browser using ONLY the local proxy initially (direct connection upstream)
const browser = await chromium.launch({ proxy: { server: dyn.url } });
const context = await browser.newContext();
const page = await context.newPage();
const { page: samePage } = await agentConnect(page, {
dynamicProxy: dyn,
onProxyLoaded: (p) => console.log("Upstream proxy loaded", p.server),
onRetry: (a, m) => console.log(`Retry ${a}/${m}`),
}).goto("https://blocked-website.example");
console.log(await samePage.title());
await browser.close();
How It Works
When you call retryWithProxy(page).goto(url), the SDK wraps around Playwright's native page.goto() and adds retry logic with optional proxy handling.
It doesn't modify Playwright itself - it just adds smart recovery behavior when a navigation fails.
Here's what happens behind the scenes:
- Normal navigation first
The SDK first calls
page.goto(url)normally, without using any proxy. If it succeeds, you get the same result as a regular Playwright call. - Error detection
If the navigation throws an error, the SDK checks if the error message, name, or code matches any of the retry patterns (defined in
retryOnorALUVIA_RETRY_ON). By default, it retries on common network errors such as:ETIMEDOUTECONNRESETnet::ERR_CONNECTION_RESETTimeoutError
- Fetch a proxy
If the error is retryable, the SDK fetches a proxy.
- By default, it uses the Aluvia API, reading your token key from
ALUVIA_API_KEY. - If you provided a custom proxyProvider, it uses that instead.
- Once a proxy is obtained, it calls
dynamicProxy.setUpstream()to configure the local proxy server to route through the new upstream proxy.
- By default, it uses the Aluvia API, reading your token key from
- Retry the navigation
It retries
page.goto()again with the same URL, applying an exponential backoff delay between attempts. The delay is calculated asbackoffMs * 2^attempt + random(0–100). - Repeat or fail gracefully
This process continues up to the
maxRetrieslimit. If all retries fail, the SDK throws the last encountered error, just like Playwright would.
FAQ
Does it always use a proxy?
No. It tries direct navigation first. Only on a retryable failure does it fetch a proxy and relaunch.
Can I plug in Bright Data, Oxylabs, or my own pool?
Yes. Implement proxyProvider.get() and return { server, username, password }.
You can integrate any proxy API, database, or in-house rotation system that follows this.
Does this modify Playwright itself?
No. The SDK doesn't patch or override Playwright's core modules.
It just wraps your existing page.goto() calls and adds retry + proxy logic externally.
Does it retry failed requests made inside the page (XHR/fetch)?
No. It only retries top-level navigations triggered by page.goto(), however, once a proxy is set up, all requests from that page (including XHR/fetch) will go through the proxy.
If you need granular retry control for API calls inside the page, handle those separately with Playwright's request interception APIs.
Does the proxy get disabled automatically?
No. Once a proxy is set for the dynamic proxy server, it stays active for all subsequent retries.
If you want to disable the proxy after a successful navigation, call dynamicProxy.setUpstream().
Does it work with Firefox or WebKit?
Yes. It supports all official Playwright browser types (chromium, firefox, and webkit).
The SDK automatically detects which browser you’re using.