Skip to content
Code Examples

Production-Ready Code Examples

Copy-paste examples for cURL, Python, and Node.js. Includes authentication, proxy rotation, session management, and framework integrations.

Basic Authentication

All proxy requests use HTTP Basic Auth with the proxy username and password from your dashboard (Residential → Generate Proxies) or from POST /api/v1/proxies/generate. Your API key is only for the REST API; it is not a proxy credential. Each generated line is host:port:username:password. These examples use the Basic plan (basic.resi.zentislabs.com:12321), where targeting such as _country-us is appended to the password.

# Basic proxy request with authentication
curl -x "http://USERNAME:PASSWORD_country-us@basic.resi.zentislabs.com:12321" -L "https://ipinfo.io/json"

Rotating Proxies

Get a new IP address for every request. Perfect for web scraping and avoiding rate limits.

# Each request gets a new IP
for i in {1..5}; do
curl -x "http://USERNAME:PASSWORD_country-us@basic.resi.zentislabs.com:12321" -s "https://ipinfo.io/json" | jq '.ip'
done

Sticky Sessions

Keep the same IP address for multiple requests. On Basic, add _session-ID after the country in the password (use letters and digits for the ID), plus an optional session length such as _lifetime-10m. Requests with the same session ID share one IP. Sticky lines generated in the dashboard or API may use a single gateway IP instead of the hostname so the exit IP stays the same; prefer those lines in production.

# Add a session ID to the password to keep the same IP
SESSION_ID="sess12345"
# All requests with the same session ID use the same IP (10-minute lifetime)
curl -x "http://USERNAME:PASSWORD_country-us_session-${SESSION_ID}_lifetime-10m@basic.resi.zentislabs.com:12321" "https://ipinfo.io/json"
curl -x "http://USERNAME:PASSWORD_country-us_session-${SESSION_ID}_lifetime-10m@basic.resi.zentislabs.com:12321" "https://target-site.com/api/data"

Country Selection

Target a country with its lowercase ISO code: add _country-us to the password on Light and Basic, or -country-us to the username on Advanced.

# Lowercase ISO 3166-1 alpha-2 codes, e.g. us, gb, de, fr, jp, ca, au, nl, sg
# United States
curl -x "http://USERNAME:PASSWORD_country-us@basic.resi.zentislabs.com:12321" "https://ipinfo.io/json"
# Germany
curl -x "http://USERNAME:PASSWORD_country-de@basic.resi.zentislabs.com:12321" "https://ipinfo.io/json"
# Japan (Advanced plan: the country goes in the username)
curl -x "http://USERNAME-country-jp:PASSWORD@advanced.resi.zentislabs.com:61236" "https://ipinfo.io/json"

Framework Integrations

Scrapy (Python)

# settings.py
DOWNLOADER_MIDDLEWARES = {
'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 1,
}
# spider.py
import scrapy
# Configure ZentisLabs proxy (credentials from the dashboard)
PROXY = 'http://USERNAME:PASSWORD_country-us@basic.resi.zentislabs.com:12321'
class MySpider(scrapy.Spider):
name = 'example'
def start_requests(self):
urls = ['https://example.com/page1', 'https://example.com/page2']
for url in urls:
# HttpProxyMiddleware reads the proxy (and its credentials) from request.meta
yield scrapy.Request(url, callback=self.parse, meta={'proxy': PROXY})
def parse(self, response):
# Each request automatically uses a different IP
yield {'title': response.css('h1::text').get()}

Puppeteer (Node.js)

const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: true,
args: [
'--proxy-server=basic.resi.zentislabs.com:12321'
]
});
const page = await browser.newPage();
// Authenticate with proxy (credentials from the dashboard; targeting goes in the password)
await page.authenticate({
username: 'USERNAME',
password: 'PASSWORD_country-us'
});
await page.goto('https://example.com');
// For new IP, create new page
const page2 = await browser.newPage();
await page2.authenticate({ username: 'USERNAME', password: 'PASSWORD_country-us' });
await page2.goto('https://example.com');
await browser.close();
})();

Selenium (Python)

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
# Configure Chrome with proxy
chrome_options = Options()
chrome_options.add_argument('--proxy-server=basic.resi.zentislabs.com:12321')
# Chrome ignores user:pass in --proxy-server, so pass the credentials
# with an auth extension or use selenium-wire, which accepts
# http://USERNAME:PASSWORD@host:port directly
driver = webdriver.Chrome(options=chrome_options)
# Navigate to site
driver.get('https://example.com')
# Each new driver instance gets new IP
driver.quit()

Error Handling

Handle common proxy errors with retries and exponential backoff.

import requests
import time
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
# Configure retry strategy
retry_strategy = Retry(
total=3,
backoff_factor=1,
status_forcelist=[429, 500, 502, 503, 504],
)
adapter = HTTPAdapter(max_retries=retry_strategy)
http = requests.Session()
http.mount("http://", adapter)
http.mount("https://", adapter)
proxies = {
'http': 'http://USERNAME:PASSWORD_country-us@basic.resi.zentislabs.com:12321',
'https': 'http://USERNAME:PASSWORD_country-us@basic.resi.zentislabs.com:12321'
}
def fetch_with_retry(url, max_retries=3):
for attempt in range(max_retries):
try:
response = http.get(url, proxies=proxies, timeout=30)
response.raise_for_status()
return response
except requests.exceptions.ProxyError as e:
print(f"Proxy error on attempt {attempt + 1}: {e}")
if attempt < max_retries - 1:
time.sleep(2 ** attempt) # Exponential backoff
else:
raise
# Usage
try:
response = fetch_with_retry('https://example.com')
print(response.text)
except Exception as e:
print(f"Failed after retries: {e}")