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 authenticationcurl -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 IPfor i in {1..5}; do curl -x "http://USERNAME:PASSWORD_country-us@basic.resi.zentislabs.com:12321" -s "https://ipinfo.io/json" | jq '.ip'doneSticky 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 IPSESSION_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 Statescurl -x "http://USERNAME:PASSWORD_country-us@basic.resi.zentislabs.com:12321" "https://ipinfo.io/json"
# Germanycurl -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.pyDOWNLOADER_MIDDLEWARES = { 'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 1,}
# spider.pyimport 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 webdriverfrom selenium.webdriver.chrome.options import Options
# Configure Chrome with proxychrome_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 sitedriver.get('https://example.com')
# Each new driver instance gets new IPdriver.quit()Error Handling
Handle common proxy errors with retries and exponential backoff.
import requestsimport timefrom requests.adapters import HTTPAdapterfrom urllib3.util.retry import Retry
# Configure retry strategyretry_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
# Usagetry: response = fetch_with_retry('https://example.com') print(response.text)except Exception as e: print(f"Failed after retries: {e}")