On this page
Proxy settings at a glance
Settings for any proxy-aware app
- Host
- proxy.packetstream.io [VERIFIED 2026-10-17]
- Port (HTTPS proxy)
- 31111 — recommended
- Port (SOCKS5)
- 31113
- Port (HTTP proxy)
- 31112 — legacy
- Username
- Your PacketStream username
- Password
- Your dashboard auth key (+ optional suffixes)
- Country suffix
-
_country-US(ISO code, uppercase) - Session suffix
-
_session-label
That is the whole configuration surface. Targeting and sessions are expressed only through the password; the host and port never change. If you are choosing a provider rather than configuring one, start with the PacketStream review.
Credentials
You need two values from the PacketStream dashboard: your username and your auth key, which acts as the proxy password. The dashboard’s Proxy Access page can also generate the key with a country suffix. The Search and Fetch APIs use a separate API key — see the API guide.
The official examples read the credentials from environment variables:
export PACKETSTREAM_USER='YOUR_USERNAME'
export PACKETSTREAM_AUTH_KEY='YOUR_AUTH_KEY'
The docs warn not to commit real credentials to a script, .env file, test fixture or container image,
and to prefer passing credentials separately from the proxy URL: a full proxy URL “is easy to expose in process
lists, exceptions, analytics, or debug logs”.
Endpoints & ports
HTTPS https://proxy.packetstream.io:31111
SOCKS5 socks5h://proxy.packetstream.io:31113
HTTP http://proxy.packetstream.io:31112 HTTPS (31111) is the recommended endpoint: it encrypts the hop from your application to
PacketStream’s gateway, and HTTPS destinations keep their own TLS through the proxy. SOCKS5 (31113)
is for clients that specifically need it; note the socks5h:// scheme, which resolves DNS at the proxy.
HTTP (31112) exists for legacy compatibility and is not recommended for new integrations.
A library that handles HTTPS websites does not necessarily support an HTTPS proxy. Some only speak plain HTTP to the proxy and tunnel HTTPS destinations through it. PacketStream’s docs say to use SOCKS5 when that is the best-supported secure option for a client, or to choose a client with HTTPS-proxy support — and never to disable certificate verification to make a configuration work.
Only outbound connections are needed: no inbound ports, NAT rules or port forwarding. If a connection fails before authentication, check the host/port pairing, outbound firewall rules, whether the client supports the scheme, and whether a corporate proxy or VPN is intercepting.
Auth format & suffixes
The username is always your PacketStream username. The password is your auth key, optionally followed by modifiers. From the endpoints & authentication page:
| Behaviour | Password value |
|---|---|
| Automatic rotation | AUTH_KEY |
| United States target | AUTH_KEY_country-US |
| Sticky workflow | AUTH_KEY_session-order42 |
| Country plus sticky workflow | AUTH_KEY_country-US_session-order42 |
Order matters: the country modifier comes before the session modifier. In code, the docs compose the password in application configuration so the final value is not written to logs:
PACKETSTREAM_AUTH_KEY + "_country-US"
PACKETSTREAM_AUTH_KEY + "_session-workflow42"
PACKETSTREAM_AUTH_KEY + "_country-US_session-workflow42" If a client only accepts a single proxy URL, the credential-in-URL form is:
https://YOUR_USERNAME:YOUR_AUTH_KEY@proxy.packetstream.io:31111 Percent-encode the username and key if you build that URL yourself (the Python and Scrapy examples below do). Use non-sensitive session labels: the docs say not to put email addresses, customer identifiers, destination credentials or other personal data in a session ID. How rotation, sessions and countries behave is covered in the sticky sessions and country targeting deep dive.
curl
The quickest check: request ipinfo.io through the HTTPS proxy and print what the destination sees.
curl --silent --show-error --fail-with-body \
--proxy 'https://proxy.packetstream.io:31111' \
--proxy-user "${PACKETSTREAM_USER}:${PACKETSTREAM_AUTH_KEY}" \
'https://ipinfo.io' \
| jq '{ip, hostname, city, region, country, loc, org, postal, timezone}' The same request over SOCKS5:
curl --proxy 'socks5h://proxy.packetstream.io:31113' \
--proxy-user "${PACKETSTREAM_USER}:${PACKETSTREAM_AUTH_KEY}" \
'https://ipinfo.io'
The docs suggest adding --connect-timeout and --max-time when a command runs unattended.
Each separate curl process opens a new proxy connection, which makes curl the simplest way to observe rotation.
Python Requests
python -m pip install requests import os
from urllib.parse import quote
import requests
username = quote(os.environ["PACKETSTREAM_USER"], safe="")
auth_key = quote(os.environ["PACKETSTREAM_AUTH_KEY"], safe="")
proxy = f"https://{username}:{auth_key}@proxy.packetstream.io:31111"
response = requests.get(
"https://ipinfo.io",
proxies={"http": proxy, "https": proxy},
timeout=30,
)
response.raise_for_status()
print(response.json())
Passing the proxies dictionary on each request stops environment proxy settings from silently
replacing the intended configuration. Note the https:// scheme on the proxy URL: this is the HTTPS
proxy on port 31111, used for both http and https destinations. Requests reuses
connections inside a Session, so consecutive requests may share an exit.
Node.js (Undici)
npm install undici import { ProxyAgent, fetch } from "undici";
const username = process.env.PACKETSTREAM_USER;
const authKey = process.env.PACKETSTREAM_AUTH_KEY;
if (!username || !authKey) {
throw new Error("Set PACKETSTREAM_USER and PACKETSTREAM_AUTH_KEY");
}
const token = Buffer.from(`${username}:${authKey}`).toString("base64");
const dispatcher = new ProxyAgent({
uri: "https://proxy.packetstream.io:31111",
token: `Basic ${token}`,
});
try {
const response = await fetch("https://ipinfo.io", {
dispatcher,
signal: AbortSignal.timeout(30_000),
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
console.log(await response.json());
} finally {
await dispatcher.close();
}
Undici’s ProxyAgent supports HTTPS proxy URIs and takes a preformatted
Proxy-Authorization token, so the credentials never appear in a URL. Closing the dispatcher in
finally releases pooled connections.
Scrapy
Scrapy needs one extra piece. Its standard proxy middleware does not make a TLS connection to an HTTPS proxy, and
it has no standard authenticated SOCKS5 downloader. PacketStream’s
Scrapy guide solves this with a loopback-only TLS bridge
using socat:
python -m pip install scrapy
export PACKETSTREAM_USER='YOUR_USERNAME'
export PACKETSTREAM_AUTH_KEY='YOUR_AUTH_KEY' socat 'TCP4-LISTEN:31110,bind=127.0.0.1,reuseaddr,fork' \
'OPENSSL:proxy.packetstream.io:31111,verify=1,commonname=proxy.packetstream.io' import os
from urllib.parse import quote
import scrapy
class PacketStreamExitSpider(scrapy.Spider):
name = "packetstream_exit"
custom_settings = {"DOWNLOAD_TIMEOUT": 30}
def start_requests(self):
username = quote(os.environ["PACKETSTREAM_USER"], safe="")
auth_key = quote(os.environ["PACKETSTREAM_AUTH_KEY"], safe="")
proxy = f"http://{username}:{auth_key}@127.0.0.1:31110"
yield scrapy.Request("https://ipinfo.io", meta={"proxy": proxy})
def parse(self, response):
yield response.json() scrapy runspider packetstream_exit.py -O -. Source: PacketStream Scrapy integration, checked 17 Oct 2026.
Scrapy sends plaintext only to the local bridge; socat verifies the gateway certificate and carries
the traffic to proxy.packetstream.io:31111 over TLS. For country targeting or a sticky session, apply
the modifiers before URL-encoding the password:
auth_key = quote(
f'{os.environ["PACKETSTREAM_AUTH_KEY"]}_country-US_session-crawl42',
safe="",
)
Set meta["proxy"] on every request path that must use PacketStream, including requests created in
callbacks. Scrapy’s downloader reuses connections, so a second request does not guarantee a new exit.
Playwright
npm install playwright
npx playwright install chromium
export PACKETSTREAM_USER='YOUR_USERNAME'
export PACKETSTREAM_AUTH_KEY='YOUR_AUTH_KEY' import { chromium } from "playwright";
const browser = await chromium.launch({
proxy: {
server: "https://proxy.packetstream.io:31111",
username: process.env.PACKETSTREAM_USER,
password: process.env.PACKETSTREAM_AUTH_KEY,
},
});
try {
const page = await browser.newPage();
await page.goto("https://ipinfo.io/json", {
waitUntil: "domcontentloaded",
timeout: 30_000,
});
console.log(JSON.parse(await page.locator("body").innerText()));
} finally {
await browser.close();
} node packetstream_playwright.mjs. Source: PacketStream Playwright integration, checked 17 Oct 2026.For targeting or a sticky session, change only the password in the launch configuration:
password: `${process.env.PACKETSTREAM_AUTH_KEY}_country-US_session-browser42`,
Every page in a browser instance shares its proxy configuration, so launch separate browsers when concurrent
workflows need different session labels. Keep https:// on the server value. An undefined
environment variable produces an authentication failure. To cut bandwidth cost, block images, fonts and media in
Playwright — see the cost per 1,000 pages.
Puppeteer
Puppeteer’s page-wide page.authenticate can also answer a destination site’s authentication
challenge, so PacketStream’s Puppeteer guide routes
Chrome through a loopback proxy-chain bridge that sends credentials only to the upstream proxy:
npm install proxy-chain puppeteer
export PACKETSTREAM_USER='YOUR_USERNAME'
export PACKETSTREAM_AUTH_KEY='YOUR_AUTH_KEY' import { anonymizeProxy, closeAnonymizedProxy } from "proxy-chain";
import puppeteer from "puppeteer";
const username = process.env.PACKETSTREAM_USER;
const authKey = process.env.PACKETSTREAM_AUTH_KEY;
if (!username || !authKey) {
throw new Error("Set PACKETSTREAM_USER and PACKETSTREAM_AUTH_KEY");
}
const upstreamProxy = new URL("https://proxy.packetstream.io:31111");
upstreamProxy.username = username;
upstreamProxy.password = authKey;
const localProxyUrl = await anonymizeProxy(upstreamProxy.href);
let browser;
try {
browser = await puppeteer.launch({
args: [`--proxy-server=${localProxyUrl}`],
});
const page = await browser.newPage();
await page.goto("https://ipinfo.io/json", {
waitUntil: "domcontentloaded",
timeout: 30_000,
});
console.log(await page.$eval("body", (body) => JSON.parse(body.innerText)));
} finally {
try {
if (browser) await browser.close();
} finally {
await closeAnonymizedProxy(localProxyUrl, true);
}
} node packetstream_puppeteer.mjs. Source: PacketStream Puppeteer integration, checked 17 Oct 2026.Set the modified password before calling anonymizeProxy:
upstreamProxy.password = `${authKey}_country-US_session-browser42`;
The guide says to use this bridge only on a single-user machine: on a shared host another local process could
find the temporary port while the script runs. Use Playwright there instead. For SOCKS5, initialise
upstreamProxy with socks5://proxy.packetstream.io:31113. Always close the anonymised
proxy.
Go
package main
import (
"fmt"
"io"
"log"
"net/http"
"net/url"
"os"
"time"
)
func main() {
proxyURL := &url.URL{
Scheme: "https",
Host: "proxy.packetstream.io:31111",
User: url.UserPassword(os.Getenv("PACKETSTREAM_USER"), os.Getenv("PACKETSTREAM_AUTH_KEY")),
}
transport := http.DefaultTransport.(*http.Transport).Clone()
transport.Proxy = http.ProxyURL(proxyURL)
client := &http.Client{Transport: transport, Timeout: 30 * time.Second}
response, err := client.Get("https://ipinfo.io")
if err != nil {
log.Fatal(err)
}
defer response.Body.Close()
body, err := io.ReadAll(response.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(body))
} Go infers proxy behaviour from the URL scheme and sends the URL’s user information as proxy authorisation. Runnable projects and Docker configurations are in the official packetstream-examples repository.
Troubleshooting
Start with a controlled preflight from the same machine or container as the failing application:
curl --verbose --show-error --fail-with-body \
--connect-timeout 15 \
--max-time 45 \
--proxy 'https://proxy.packetstream.io:31111' \
--proxy-user "${PACKETSTREAM_USER}:${PACKETSTREAM_AUTH_KEY}" \
'https://ipinfo.io' \
--output /tmp/packetstream-ipinfo.json | Symptom | Check / fix |
|---|---|
| Authentication fails | Username is the proxy username; password is the auth key including intended modifiers; no stray whitespace or line breaks; scheme and port paired; client sends proxy auth, not destination auth. Don’t retry — stop and fix. |
| Connection fails before auth | Host/port pairing, outbound firewall, client support for the scheme, VPN or corporate proxy interference. |
| TLS / certificate errors | Correct scheme and port; current trust store; no inspection proxy replacing certificates; library really supports TLS to an HTTPS proxy. Test with a current curl. Never disable verification in production. |
| Rotation returns the same exit | Rotation is per new connection; your client is probably reusing pooled connections. A new connection can also legitimately get the same IP. |
| Sticky session fails | The sharer behind the exit disconnected. Stop the workflow, pick a new session label, restart from a checkpoint. Sessions are not static IPs. |
| Country-targeted request fails | No exit available in that country right now — it fails rather than using another country. Use bounded backoff; keep it separate from auth and destination failures. |
| Exit is in the wrong country | Check the code. An unrecognised country code is ignored and the request can exit anywhere (e.g. use GB, not UK). Pick the country from the dashboard’s Location list to get a valid code. |
| Surprising city or region | Expected: sub-country labels from IP databases are approximate. Targeting is set by country code. |
| Timeouts | Separate limits for proxy connect, destination wait, whole request and total retries. Retry only plausibly transient failures, with exponential backoff and jitter. |
If you contact support, send the timestamp and timezone, protocol and port, client and version, OS or container image, requested country, rotation or sticky, and a sanitised error — never the auth key or a full authenticated proxy URL. Contact support at help@packetstream.io or through the contact form.