Skip to content

ProxyHatCom/stagehand-proxyhat

Repository files navigation

stagehand-proxyhat

Route Stagehand's local browser through ProxyHat residential proxies — a pinned sticky IP per agent session, geo-targeting, and rotating IPs.

CI Compatible with Stagehand latest npm License: MIT

Tip

Recommended proxies — ProxyHat residential IPs. Every feature in this package is tested end-to-end against ProxyHat and works great. First-class integration; also works with any proxy, or none.

Why

Stagehand drives an AI agent over a browser (Playwright under the hood). When you run it locally (env: "LOCAL"), that browser goes out from your own datacenter IP — which gets your agent blocked, CAPTCHA'd, and rate-limited. This package plugs ProxyHat's residential IPs (50M+ across 148+ countries) into Stagehand's local browser through its first-class proxy option, and maps each Stagehand instance to one pinned residential IP for its whole agent session — mimicking a real user. No boilerplate.

Install

npm install stagehand-proxyhat

@browserbasehq/stagehand is a peer dependency — bring your own version (>=2).

Quick start

import { Stagehand } from "@browserbasehq/stagehand";
import { proxyhatStagehandConfig } from "stagehand-proxyhat";

// An API key auto-selects an active residential sub-user. `env` defaults to
// "LOCAL"; your own Stagehand config (model, systemPrompt, …) is preserved.
const config = await proxyhatStagehandConfig(
  { apiKey: process.env.PROXYHAT_API_KEY, targeting: { country: "us" } },
  { model: "openai/gpt-4o" },
);

const stagehand = new Stagehand(config);
await stagehand.init();

const page = stagehand.context.pages()[0];
await page.goto("https://httpbin.org/ip"); // exits from a US residential IP

Get an API key at proxyhat.com.

Where the proxy lands

Stagehand's local browser reads its proxy from localBrowserLaunchOptions.proxy (a Playwright-shaped { server, username, password, bypass }). proxyhatStagehandConfig returns a full Stagehand constructor config (v3 V3Options, formerly ConstructorParams) with that field filled in; proxyhatProxy returns just the proxy object if you'd rather set it yourself.

The proxy only applies to env: "LOCAL". In env: "BROWSERBASE" the browser runs in Browserbase's cloud and proxies are configured there instead — proxyhatStagehandConfig preserves whatever env you pass but the proxy field is only honoured locally.

Credentials

Pass them explicitly or via environment variables — options win over env:

Option Env var Notes
apiKey PROXYHAT_API_KEY Auto-selects an active sub-user with remaining traffic
subUser PROXYHAT_SUBUSER Pick a specific sub-user by uuid or name (with an API key)
username PROXYHAT_USERNAME Explicit gateway proxy_username (skips the API)
password PROXYHAT_PASSWORD Explicit gateway proxy_password

Targeting

const config = await proxyhatStagehandConfig({
  apiKey: process.env.PROXYHAT_API_KEY,
  protocol: "http", // or "socks5"
  targeting: {
    country: "us",      // ISO code or "any" (default)
    region: "california",
    city: "new_york",
    filter: "high",     // AI IP-quality tier
  },
  stickyTtl: "30m",     // sticky-session lifetime (default "30m")
});

Sticky IP per agent session

By default this package pins each Stagehand instance to one ProxyHat residential IP: a fresh sticky id is minted per call, so every request the agent makes during its session keeps that same IP, like a real user. Close the browser and the IP is dropped. Build a second Stagehand instance and it gets its own distinct pinned IP.

Want a fresh IP on every request instead? Turn stickiness off — the gateway rotates the exit IP per connection:

const config = await proxyhatStagehandConfig({ apiKey, sticky: false });

Build the proxy object yourself

Already have a Stagehand config? Use proxyhatProxy for just the proxy object and drop it into localBrowserLaunchOptions.proxy:

import { Stagehand } from "@browserbasehq/stagehand";
import { proxyhatProxy } from "stagehand-proxyhat";

const proxy = await proxyhatProxy({ apiKey: process.env.PROXYHAT_API_KEY, targeting: { country: "us" } });

const stagehand = new Stagehand({
  env: "LOCAL",
  model: "openai/gpt-4o",
  localBrowserLaunchOptions: { headless: false, proxy },
});
await stagehand.init();

Fully offline and synchronous once you have credentials:

import { buildStagehandProxy, resolveCredentials } from "stagehand-proxyhat";

const credentials = await resolveCredentials({ apiKey: process.env.PROXYHAT_API_KEY });
const proxy = buildStagehandProxy(credentials, { targeting: { country: "us" } });
// -> { server: "http://gate.proxyhat.com:8080", username: "…-country-us-sid-…-ttl-30m", password: "…" }

How it works

proxyhatProxy (and proxyhatStagehandConfig) resolves your gateway credentials once (via the official proxyhat SDK), then builds the proxy object Stagehand's local browser expects: server points at the ProxyHat gateway (gate.proxyhat.com:8080 for HTTP, :1080 for SOCKS5) and username carries the targeting grammar. With stickiness on it mints a sid/ttl so the session keeps one pinned IP; with sticky: false it omits the sid so the gateway hands out a fresh residential IP per connection.

License

MIT © ProxyHat

About

Route Stagehand (AI browser automation) through ProxyHat residential proxies — sticky per-session IPs, geo-targeting, rotation.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors