Use cases · Web scraping
Residential proxies for web scraping
Collect public web data through real home connections. Rotate the exit on every new connection, or keep one exit for a multi-step job. $1.00/GB, no subscription.
Rotation by default
Each new proxy connection gets a new exit selection. Requests sent over one open connection keep its exit.
Sticky when you need it
Add _session-label to the auth key to keep one exit across connections. Each new connection restarts a 60-minute timer.
Country targeting
Add _country-DE to pick the exit country. If that country has no available exit, the request fails. Use a valid uppercase code: an unknown code is ignored.
Set up a scraper in Python
You need the username and auth key from the Proxy Access page of the dashboard. Keep them in environment variables:
export PACKETSTREAM_USER='your_username'
export PACKETSTREAM_AUTH_KEY='your_auth_key'
This scraper uses the HTTPS gateway on port 31111. It picks a country and retries a few times with backoff, with a new exit on each attempt. It stops on wrong credentials and on pages that are gone:
import os
import time
from urllib.parse import quote
import requests
USER = quote(os.environ["PACKETSTREAM_USER"], safe="")
AUTH_KEY = os.environ["PACKETSTREAM_AUTH_KEY"]
def proxy_url(country=None, session=None):
password = AUTH_KEY
if country:
password += f"_country-{country}"
if session:
password += f"_session-{session}"
return f"https://{USER}:{quote(password, safe='')}@proxy.packetstream.io:31111"
def fetch(url, country="US", attempts=3):
proxy = proxy_url(country)
for attempt in range(1, attempts + 1):
try:
# A new Session opens a new proxy connection, so each
# attempt gets a new exit selection.
with requests.Session() as session:
response = session.get(
url, proxies={"http": proxy, "https": proxy}, timeout=30
)
except requests.exceptions.ProxyError as error:
if "Tunnel connection failed: 407" in str(error):
raise # Wrong username or auth key: retrying won't help.
response = None # No exit was available: try again.
except requests.RequestException:
response = None
if response is not None:
if response.ok:
return response
if response.status_code in (404, 410):
# The page is gone: retrying won't help.
response.raise_for_status()
time.sleep(2 ** attempt)
raise RuntimeError(f"gave up after {attempts} attempts: {url}")
page = fetch("https://example.com/products?page=1")
print(page.status_code, len(page.content), "bytes")
The same proxy URL works in most HTTP clients. For other languages, see language integrations. For Scrapy, use the Scrapy guide. For pages that need JavaScript, use a headless browser such as Playwright.
Rotate or stick?
| Job | Use | Password |
|---|---|---|
| Many independent pages, such as product or listing pages | Rotation | AUTH_KEY_country-US |
| Several steps that must come from one IP, such as page 1 then page 2 of a search | Sticky session | AUTH_KEY_country-US_session-job42 |
Use one session label per job, and a new label for each job that runs at the same time. Browsers and HTTP libraries reuse connections, so a new request does not always mean a new exit. Read rotation and sticky sessions for the details.
Keep the cost down
You pay for every byte that goes through the gateway, including error pages and retries. Three things help most:
- Measure your pages. Page size decides the bill. The bandwidth calculator turns pages and page size into GB and dollars.
- Skip what you don’t parse. An HTTP client that fetches only the HTML uses much less than a browser that also loads images, fonts and scripts.
- Limit retries. Retry in one place in your code, with a small limit. Retries in several layers multiply traffic.
How to estimate proxy bandwidth and how to plan proxy concurrency cover this in more depth.
Honest limits
- Sites can still block you. A residential IP is not a pass. Sites can rate-limit you, block you, or show a CAPTCHA. We don’t solve CAPTCHAs.
- The proxy doesn’t run JavaScript. It forwards your traffic. If a page builds its content with JavaScript, your browser or client must run it.
- Country only. You can pick the country. You can’t pick a city, region or ISP.
- Exits are real homes. Speed varies, and a Packeter can go offline. Use timeouts and retries.
- Only collect what you may. Collect public data, follow each site’s terms, and don’t collect personal data unlawfully. Our terms forbid getting around logins or other access controls.
Need clean text, not raw HTML?
The Fetch API reads one public page and returns it as Markdown, for $0.0025 per page that returns content. It does not run JavaScript. It uses the same balance as your proxy traffic.
Pricing
Pay for what you use.
$1.00 per GB
Rotating and sticky traffic cost the same, in every country.
$50 minimum, no expiry
Prepaid balance with no subscription. Purchased balance does not expire.
Price monitoring
Check public prices from the country you care about, and pull Google Shopping offers as JSON from the same balance.
Read moreSEO and SERP rank tracking
Track Google rankings by country, city and device as JSON, and check your own localized pages through residential proxies.
Read moreAd verification
Follow your tracking links and landing pages from each country, and check your Google text ads as JSON.
Read more