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

playwright-proxyhat

v0.1.1

Published

Route Playwright browsers through ProxyHat residential proxies — a pinned sticky IP per browser context, geo-targeting, and rotating IPs.

Readme

playwright-proxyhat

Route Playwright browsers through ProxyHat residential proxies — a pinned sticky IP per browser context, geo-targeting, and rotating IPs.

CI Compatible with Playwright 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

Driving a browser from datacenter IPs gets you blocked, CAPTCHA'd, and rate-limited. This package plugs ProxyHat's residential IPs (50M+ across 148+ countries) into Playwright through its first-class proxy option — set at launch, or per browser context, which is the real hook: Playwright isolates each context (its own cookies, storage, and IP), so this package maps each context to one pinned residential IP, mimicking a real user. No boilerplate; works with Chromium, Firefox, and WebKit.

Install

npm install playwright-proxyhat

playwright is a peer dependency — bring your own version (>=1.30).

Quick start

import { chromium } from "playwright";
import { newProxyHatContext } from "playwright-proxyhat";

const browser = await chromium.launch();

// An API key auto-selects an active residential sub-user:
const context = await newProxyHatContext(browser, {
  apiKey: process.env.PROXYHAT_API_KEY,
  targeting: { country: "us" },
});

const page = await context.newPage();
await page.goto("https://httpbin.org/ip"); // exits from a US residential IP

Get an API key at proxyhat.com.

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 context = await newProxyHatContext(browser, {
  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 browser context

By default this package maps each context to one pinned ProxyHat residential IP: a fresh sticky id is minted per context, so concurrent contexts get distinct exit IPs — and every request inside a context keeps that same IP for the context's lifetime, like a real user. Close the context and the IP is dropped.

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

await newProxyHatContext(browser, { apiKey, sticky: false });

One IP for the whole browser

Prefer a single IP shared by every context? Set the proxy at launch instead:

import { chromium } from "playwright";
import { proxyhatProxy } from "playwright-proxyhat";

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

@playwright/test fixture

Give every test its own context on a fresh sticky residential IP by overriding the context fixture:

import { test as base } from "@playwright/test";
import { newProxyHatContext } from "playwright-proxyhat";

export const test = base.extend({
  context: async ({ browser }, use) => {
    const context = await newProxyHatContext(browser, {
      apiKey: process.env.PROXYHAT_API_KEY,
      targeting: { country: "us" },
    });
    await use(context);
    await context.close();
  },
});

A runnable version lives in examples/fixture.ts.

Advanced: build the proxy object yourself

Need to combine ProxyHat with your own context logic? Use the lower-level helpers. proxyhatProxy returns a plain Playwright proxy object; proxyhatContextOptions wraps it as { proxy } to spread into newContext:

import { chromium } from "playwright";
import { proxyhatContextOptions } from "playwright-proxyhat";

const browser = await chromium.launch();
const context = await browser.newContext({
  ...(await proxyhatContextOptions({ apiKey: process.env.PROXYHAT_API_KEY })),
  locale: "en-US",
  viewport: { width: 1280, height: 800 },
});

Fully offline and synchronous once you have credentials:

import { buildPlaywrightProxy, resolveCredentials } from "playwright-proxyhat";

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

How it works

proxyhatProxy (and newProxyHatContext) resolves your gateway credentials once (via the official proxyhat SDK), then builds a Playwright proxy object: 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 context 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