npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

stagehand-proxyhat

v0.1.1

Published

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

Downloads

271

Readme

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