Integrations

Anything that speaks SOCKS5 works with p2proxy. Point it at socks5://localhost:1080 (or whatever port you’ve configured) and you’re done.

Playwright

import { chromium } from "playwright";

const browser = await chromium.launch({
  proxy: { server: "socks5://localhost:1080" },
});
const page = await browser.newPage();
await page.goto("https://example.com");

For per-context proxies (Playwright ≥ 1.29):

const context = await browser.newContext({
  proxy: { server: "socks5://localhost:1080" },
});

Puppeteer

Puppeteer takes proxy via launch args:

import puppeteer from "puppeteer";

const browser = await puppeteer.launch({
  args: ["--proxy-server=socks5://localhost:1080"],
});

curl

curl --socks5-hostname localhost:1080 https://example.com

Python requests (with PySocks)

import requests

proxies = {
  "http":  "socks5h://localhost:1080",
  "https": "socks5h://localhost:1080",
}
r = requests.get("https://ifconfig.me", proxies=proxies)
print(r.text)

The socks5h:// scheme resolves DNS through the proxy. Use socks5:// if you want local resolution.

Chrome / Chromium

Launch Chrome with:

google-chrome \
  --proxy-server="socks5://localhost:1080" \
  --user-data-dir=/tmp/chrome-p2proxy

Use a fresh --user-data-dir so you don’t taint your normal profile.

Firefox

Settings → Network Settings → Manual proxy configuration → SOCKS Host: localhost, Port: 1080. Tick SOCKS v5 and Proxy DNS when using SOCKS v5.

WireGuard (whole-device tunnel)

For anything that can’t be pointed at a SOCKS5 proxy — a phone, a desktop app with no proxy setting, everything behind a router — run the server in WireGuard mode instead and connect with a stock WireGuard client.

# Config.yaml
servers:
  - protocol: WireGuard
    port: 51820
    host: 0.0.0.0
    country: NL
    wireguard:
      private_key: <contents of server.key>
      address: 10.7.0.1/24
      dns: 1.1.1.1
      peers:
        - public_key: <contents of laptop.pub>
          allowed_ips:
            - 10.7.0.2/32
# laptop.conf — wg-quick, or import into the macOS / iOS / Android app
[Interface]
PrivateKey = <contents of laptop.key>
Address = 10.7.0.2/32
DNS = 1.1.1.1

[Peer]
PublicKey = <contents of server.pub>
Endpoint = <host running p2proxy>:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25
wg-quick up ./laptop.conf
curl https://ifconfig.me      # the peer's IP, not yours

p2proxy terminates the tunnel in userspace — it needs no root, no kernel module and no TUN device on the p2proxy host (your client still creates one locally, as it always does). Key generation, allowed_ips semantics, MTU and throughput tuning — and the routing trap that takes your machine offline if you run the client on the p2proxy host — are covered on the WireGuard / VPN page.

Full-tunnel via tun2socks

If you’d rather keep a SOCKS5 listener and tunnel at the OS level, tun2socks routes an entire interface through it.

High-level steps:

  1. Create a TUN device.
  2. Point tun2socks at socks5://localhost:1080.
  3. Add a default route through the TUN device for the subnets you want to tunnel.

See the tun2socks README for the precise invocation on your platform. WireGuard mode above is usually the simpler path.

Picking the right SOCKS5 dialect

Most tools speak SOCKS5 well, but DNS handling varies:

  • socks5:// — client resolves DNS locally, then asks p2proxy for the IP.
  • socks5h:// — p2proxy (via the peer) resolves DNS. Use this when DNS resolution from your machine would itself leak which sites you’re visiting, or when local DNS would resolve differently from the peer’s location.

For most scraping / multi-geo workloads you want socks5h://.