Documentation

Getting your proxies working

Formats, targeting, sessions and the differences between the three networks — everything you need to go from a generated list to working traffic.

ISP proxies

An ISP purchase is a batch: a set of dedicated IPs sharing one credential pair, valid for a fixed term. Bandwidth is unlimited, so the only thing that runs out is time — the remaining validity is on the plan page.

You can authenticate three ways, switchable at any time:

  • Username & password — generated for you, shared across the batch.
  • IP whitelist — no credentials; only the addresses you list may connect.
  • SOCKS5 — SOCKS5 credentials, also generated automatically.
Switching authentication regenerates the credentials for every IP in the batch. Update your tools straight afterwards or connections will start failing.

Rotating residential

Residential is bought as a gigabyte allowance, not as a fixed set of IPs. You generate proxy strings on demand and every request draws from the same allowance. Data does not expire, and topping up merges into the same plan without changing your credentials.

curl -x "user_9fx-us-california:pass@residential.natproxies.com:9000" \
     https://api.ipify.org

Mobile 4G/5G

Mobile works the same way as residential but is backed by real carrier addresses shared by thousands of handsets, which makes them the hardest addresses to distinguish from an ordinary phone.

Mobile strings are colon-delimited rather than URL-form, and geo-targeting is country and city only — there is no state filter.

mobile.your-domain.com:5555:pkg-country-us-session-1:k5fcv99xfa1e61je

Geo-targeting

Choose a country when you generate a list. Residential additionally accepts a state or region and a city; mobile accepts a city. Narrower targeting draws from a smaller pool, so if a city returns very few working exits, widen to the state or country.

Sessions

By default every request gets a new exit IP. A sticky session holds the same exit for a set duration, which is what you want for anything that carries a login or a cart across several requests.

  • Rotating — new IP per request. Best for scraping breadth.
  • Sticky — same IP for up to 30 minutes. Best for sessions and checkouts.

Python

Every example uses user:pass authentication. If your batch is on IP whitelist instead, drop the credentials and connect to host:port directly.

# requests
import requests

proxy = "http://USER:PASS@HOST:PORT"
r = requests.get(
    "https://api.ipify.org?format=json",
    proxies={"http": proxy, "https": proxy},
    timeout=30,
)
print(r.json())          # the exit IP you are using

For many requests, reuse the session rather than reconnecting each time:

session = requests.Session()
session.proxies = {"http": proxy, "https": proxy}

for url in urls:
    r = session.get(url, timeout=30)

httpx, if you prefer async:

import httpx

async with httpx.AsyncClient(proxy="http://USER:PASS@HOST:PORT") as client:
    r = await client.get("https://example.com")
SOCKS5 needs an extra package: pip install requests[socks], then usesocks5://USER:PASS@HOST:PORT. Use socks5h:// to resolve DNS through the proxy rather than locally — which is usually what you want, since local DNS leaks your real location.

Node.js

// undici — built into modern Node
import { ProxyAgent, request } from 'undici'

const agent = new ProxyAgent('http://USER:PASS@HOST:PORT')
const { body } = await request('https://api.ipify.org?format=json', {
  dispatcher: agent,
})
console.log(await body.json())

With axios, via an agent:

import axios from 'axios'
import { HttpsProxyAgent } from 'https-proxy-agent'

const agent = new HttpsProxyAgent('http://USER:PASS@HOST:PORT')
const { data } = await axios.get('https://example.com', {
  httpAgent: agent,
  httpsAgent: agent,
})
Set httpsAgent as well as httpAgent. Setting only the first is the most common reason an axios request quietly bypasses the proxy entirely — nothing errors, the traffic simply goes out from your own IP.

cURL

# HTTP proxy
curl -x "http://USER:PASS@HOST:PORT" https://api.ipify.org

# SOCKS5, resolving DNS through the proxy
curl -x "socks5h://USER:PASS@HOST:PORT" https://api.ipify.org

# IP-whitelisted batch — no credentials needed
curl -x "http://HOST:PORT" https://api.ipify.org

# Check what a site sees, with timing
curl -x "http://USER:PASS@HOST:PORT" \
     -w "\n%{http_code} in %{time_total}s\n" \
     -o /dev/null -s https://example.com

The first command is the fastest way to confirm a proxy works at all: it returns the exit IP. If that IP is the proxy's rather than yours, everything downstream is configuration.

Playwright

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(
        proxy={
            "server": "http://HOST:PORT",
            "username": "USER",
            "password": "PASS",
        }
    )
    page = browser.new_page()
    page.goto("https://api.ipify.org")
    print(page.content())
    browser.close()

Node:

const browser = await chromium.launch({
  proxy: { server: 'http://HOST:PORT', username: 'USER', password: 'PASS' },
})
Credentials go in username and password, not in the server URL. Chromium ignores credentials embedded in the proxy URL, sohttp://user:pass@host:port silently authenticates as nobody.

For a different exit per browser context, launch one browser and pass a separate proxy per context:

const context = await browser.newContext({
  proxy: { server: 'http://HOST:PORT', username: 'USER', password: 'PASS' },
})

Selenium

Selenium is the awkward one: Chrome's --proxy-server flag accepts no credentials. With an IP-whitelisted batch it is trivial:

from selenium import webdriver

opts = webdriver.ChromeOptions()
opts.add_argument("--proxy-server=http://HOST:PORT")
driver = webdriver.Chrome(options=opts)
driver.get("https://api.ipify.org")
For user:pass authentication, whitelist your server's IP instead and use the snippet above. The usual workaround — a generated extension that fills the auth prompt — adds a moving part that breaks on Chrome updates, and it is avoidable.

Firefox, with SOCKS5:

from selenium import webdriver

profile = webdriver.FirefoxProfile()
profile.set_preference("network.proxy.type", 1)
profile.set_preference("network.proxy.socks", "HOST")
profile.set_preference("network.proxy.socks_port", PORT)
profile.set_preference("network.proxy.socks_remote_dns", True)
driver = webdriver.Firefox(firefox_profile=profile)

Scrapy

# settings.py
DOWNLOADER_MIDDLEWARES = {
    "scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware": 110,
}

# middlewares.py — set the proxy per request
class ProxyMiddleware:
    def process_request(self, request, spider):
        request.meta["proxy"] = "http://USER:PASS@HOST:PORT"
Set CONCURRENT_REQUESTS and DOWNLOAD_DELAY deliberately. A rotating pool spreads addresses, but a hundred simultaneous requests still arrive at one site as a hundred simultaneous requests.

Troubleshooting

  • 407 Proxy Authentication Required — the credentials changed, usually because the batch's authentication mode was switched. Regenerate the list.
  • Connection refused on an ISP batch — if it is on IP whitelist mode, check your current public IP is still on the list.
  • Traffic stops on a bandwidth plan — check the usage bar on the plan page. An exhausted allowance stops serving until you top up.
  • Very few IPs for a city — widen the targeting to the state or country.
Still stuck? Get in touch with your order number and we will look at it directly.