Authentication Guide ZentisLabs supports two authentication methods: API key (Bearer token) for REST API access and username:password for direct proxy connections. This guide covers both methods with code examples in cURL, Python, and Node.js.
Method 1: API Key AuthenticationUse your API key as a Bearer token in the Authorization header for all REST API requests. You can generate API keys from the Dashboard .
cURL bash
curl -X GET "https://api.zentislabs.com/v1/proxies/pools" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "X-Request-Id: req_$(date +%s)"Python (requests) python
import requests
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.zentislabs.com/v1"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
# List available proxy pools
response = requests.get(f"{BASE_URL}/proxies/pools", headers=headers)
if response.status_code == 200:
pools = response.json()["data"]
for pool in pools:
print(f"Pool: {pool['name']} — {pool['type']} — {pool['country']}")
else:
print(f"Error {response.status_code}: {response.text}")Node.js (axios) typescript
import axios from "axios";
const API_KEY = process.env.ZENTISLABS_API_KEY!;
const client = axios.create({
baseURL: "https://api.zentislabs.com/v1",
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
timeout: 10000,
});
// List proxy pools
const { data } = await client.get("/proxies/pools");
console.log("Available pools:", data.data);
// Resolve a proxy
const proxy = await client.post("/proxies/resolve", {
pool: "residential-eu",
country: "DE",
session: "scrape-session-42",
});
console.log("Proxy:", proxy.data.host, proxy.data.port); Method 2: Username:Password Proxy AuthFor direct proxy connections (HTTP/HTTPS/SOCKS5), authenticate using your proxy username and password. The format encodes targeting parameters directly in the username string.
Username Format text
Format: customer-USERNAME-cc-COUNTRY-sessid-SESSION
Examples:
customer-john_doe-cc-US → rotating US IP
customer-john_doe-cc-DE-sessid-abc123 → sticky DE session
customer-john_doe-cc-GB-city-london → London, UK IP
customer-john_doe-cc-JP-sesstype-residential → residential JP IPcURL with Proxy Auth bash
# Rotating residential proxy (US)
curl -x "http://customer-USERNAME-cc-US:PASSWORD@proxy.zentislabs.com:7777" \
"https://httpbin.org/ip"
# Sticky session (Germany, 10-minute session)
curl -x "http://customer-USERNAME-cc-DE-sessid-mysession1:PASSWORD@proxy.zentislabs.com:7777" \
"https://httpbin.org/ip"
# SOCKS5 connection
curl --socks5 "customer-USERNAME-cc-US:PASSWORD@proxy.zentislabs.com:1080" \
"https://httpbin.org/ip"Python with Proxy Auth python
import requests
USERNAME = "customer-john_doe-cc-US-sessid-scrape001"
PASSWORD = "YOUR_PROXY_PASSWORD"
PROXY_HOST = "proxy.zentislabs.com"
PROXY_PORT = 7777
proxies = {
"http": f"http://{USERNAME}:{PASSWORD}@{PROXY_HOST}:{PROXY_PORT}",
"https": f"http://{USERNAME}:{PASSWORD}@{PROXY_HOST}:{PROXY_PORT}",
}
response = requests.get("https://httpbin.org/ip", proxies=proxies, timeout=30)
print("Your proxy IP:", response.json()["origin"])
# With session persistence for multi-request flows
session = requests.Session()
session.proxies = proxies
for i in range(5):
r = session.get("https://httpbin.org/ip")
print(f"Request {i+1}: {r.json()['origin']}")Node.js with Proxy Auth typescript
import axios from "axios";
import { HttpsProxyAgent } from "https-proxy-agent";
const proxyUrl = "http://customer-USERNAME-cc-US:PASSWORD@proxy.zentislabs.com:7777";
const agent = new HttpsProxyAgent(proxyUrl);
const response = await axios.get("https://httpbin.org/ip", {
httpsAgent: agent,
timeout: 30000,
});
console.log("Proxy IP:", response.data.origin); Error HandlingCommon authentication errors and how to handle them:
401 Unauthorized Invalid or expired API key. Check that you are passing the correct key and it has not been revoked.
json
{
"error": "unauthorized",
"message": "Invalid or expired API key",
"code": 401
}403 Forbidden Key is valid but lacks permissions. Check scopes and IP allowlist configuration.
json
{
"error": "forbidden",
"message": "Key does not have 'proxy:write' scope",
"code": 403
}429 Rate Limited Too many requests. Implement exponential backoff and respect the Retry-After header.
python
import time
import requests
def make_request_with_retry(url, headers, max_retries=3):
for attempt in range(max_retries):
response = requests.get(url, headers=headers)
if response.status_code == 429:
retry_after = int(response.headers.get("Retry-After", 2 ** attempt))
print(f"Rate limited. Retrying in {retry_after}s...")
time.sleep(retry_after)
continue
return response
raise Exception("Max retries exceeded") IP AllowlistingRestrict API key usage to known egress IPs for server-to-server traffic. Configure allowlists in the Dashboard or via API.
json
{
"key_id": "key_prod_checkout",
"allowlist": ["203.0.113.0/28", "198.51.100.19/32"],
"scopes": ["proxy:read", "proxy:write", "pools:read"],
"expires_at": "2026-06-01T00:00:00Z"
} Key Rotation Best Practices RecommendedRotate production keys every 30 days Use dual-key rollout: activate new key before revoking old Create one key per service (crawler, bot, analytics) Set expiration dates on all keys Use environment variables, never hardcode keys Log and alert on failed auth attempts by key ID AvoidSharing keys across environments (dev/staging/prod) Committing keys to version control Using a single key for all services Keys without expiration or IP restrictions Rotating immediately after personnel changes (no transition period) Automated Rotation Script python
import requests
import os
API_KEY = os.environ["ZENTISLABS_API_KEY"]
BASE_URL = "https://api.zentislabs.com/v1"
# Step 1: Create new key
new_key = requests.post(
f"{BASE_URL}/keys",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"name": "crawler-prod-v2",
"scopes": ["proxy:read", "proxy:write"],
"expires_in_days": 30,
},
).json()
print(f"New key created: {new_key['key_id']}")
# Step 2: Update your secret manager with new_key["api_key"]
# Step 3: Verify new key works
# Step 4: Revoke old key after transition period
requests.delete(
f"{BASE_URL}/keys/{old_key_id}",
headers={"Authorization": f"Bearer {API_KEY}"},
) Security ChecklistAPI keys stored in environment variables or secret manager IP allowlisting enabled for production keys Separate keys per environment (dev / staging / prod) Key rotation policy documented and automated Failed auth monitoring and alerting configured Least-privilege scopes applied to every key HTTPS enforced for all API and proxy connections Audit logs reviewed monthly for anomalies Next: Configure Proxy Pools Apply auth best practices to real routing policies and geo-targeting.
Proxy Configuration