Skip to content
Security Baseline

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 Authentication

Send your API key in the X-API-Key header, or as a Bearer token in the Authorization header, on every REST API request. Your key is ready in Dashboard → Settings, where you can copy or regenerate it. You can also create up to 10 additional named keys there - one per integration - and revoke each on its own; they work exactly like the primary key (details).

cURL

bash
curl -X GET "https://api.zentislabs.com/api/v1/proxies/list" \
-H "X-API-Key: YOUR_API_KEY"

Python (requests)

python
import requests
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.zentislabs.com/api"
headers = {
"X-API-Key": API_KEY,
"Content-Type": "application/json",
}
# List your ISP proxies (static IPs)
response = requests.get(f"{BASE_URL}/v1/proxies/list", headers=headers)
if response.status_code == 200:
data = response.json()["proxies"]
print(f"Active ISP proxies: {len(data)}")
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/api",
headers: {
"X-API-Key": API_KEY,
"Content-Type": "application/json",
},
timeout: 10000,
});
// List your ISP proxies (static IPs)
const { data } = await client.get("/v1/proxies/list");
console.log("Active ISP proxies:", data.proxies.length);
// Generate a proxy
const proxy = await client.post("/v1/proxies/generate", {
provider: "basic",
country: "DE",
sessionType: "rotating",
count: 1,
});
console.log("Proxies:", proxy.data.proxies); // ["host:port:username:password", ...]

Method 2: Username:Password Proxy Auth

For direct proxy connections (HTTP/HTTPS), authenticate with the proxy username and password from your dashboard. Targeting parameters (country, state and city, session) are appended to the password on Light and Basic. Advanced takes country and session only, appended to the username.

Credential Format

text
Light USERNAME:PASSWORD_country-cc[_state-STATE[-city-CITY]][_session-ID]
Basic USERNAME:PASSWORD_country-cc[_state-STATE[-city-CITY]][_session-ID[_lifetime-Nm]]
Advanced USERNAME-country-cc[-session-ID[-sessionduration-MINUTES]]:PASSWORD
cc = lowercase country code; STATE / CITY = lowercase names without spaces
Examples (Basic, basic.resi.zentislabs.com:12321):
USERNAME:PASSWORD_country-us → rotating US IP
USERNAME:PASSWORD_country-de_session-abc123_lifetime-10m → sticky DE session, 10 minutes
USERNAME:PASSWORD_country-gb_state-england-city-london → London, UK IP
Example (Advanced, advanced.resi.zentislabs.com:61236):
USERNAME-country-us-session-abc123:PASSWORD → sticky US session
Tip: Dashboard → Proxies → Generate outputs ready-made lines for your plan.

cURL with Proxy Auth

bash
# Rotating residential proxy (US)
curl -x "http://USERNAME:PASSWORD_country-us@basic.resi.zentislabs.com:12321" \
"https://httpbin.org/ip"
# Sticky session (Germany, 10-minute session)
curl -x "http://USERNAME:PASSWORD_country-de_session-mysession1_lifetime-10m@basic.resi.zentislabs.com:12321" \
"https://httpbin.org/ip"
# Advanced plan - targeting goes on the USERNAME instead of the password
curl -x "http://USERNAME-country-us:PASSWORD@advanced.resi.zentislabs.com:61236" \
"https://httpbin.org/ip"

Python with Proxy Auth

python
import requests
USERNAME = "USERNAME"
PASSWORD = "PASSWORD_country-us_session-scrape001" # Basic: country + sticky session go in the password
PROXY_HOST = "basic.resi.zentislabs.com"
PROXY_PORT = 12321
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://USERNAME:PASSWORD_country-us@basic.resi.zentislabs.com:12321";
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 Handling

Common authentication errors and how to handle them:

401 Unauthorized

Missing or invalid API key, or the account is suspended. Check that you are sending your current key: regenerating it replaces the old one immediately.

json
{
"success": false,
"error": "Invalid API key"
}

403 Forbidden

The key is valid, but there is no bandwidth on the plan you asked to generate. Top up that plan in the dashboard and try again.

json
{
"success": false,
"error": "No basic bandwidth purchased. Buy bandwidth first."
}

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")

API Key Management

Each account has one API key. It starts with zl_live_ followed by 48 hex characters and never expires; regenerating it in the dashboard replaces it immediately. Keep it in an environment variable or a secrets manager and never expose it in frontend code.

Key Rotation Best Practices

Recommended

  • Give each integration its own named key, so a leak means revoking one key, not all
  • Keep keys in one place (secret manager or .env) that every service reads
  • Regenerate it on a schedule you can support, and whenever it may have leaked
  • Plan a short maintenance window: the old key stops working immediately
  • Use environment variables, never hardcode keys
  • Log and alert on 401 responses so a revoked key is noticed quickly

Avoid

  • Committing keys to version control
  • Putting the key in browser or mobile-app code
  • Sharing the key in chat, tickets or screenshots

How to rotate

  1. Open the dashboard → Settings and click Regenerate API key. The old key stops working at once.
  2. Update your secret manager or .env with the new key and restart the services that read it.
  3. Check the new key: GET /api/v1/account with X-API-Key returns your account.

Security Checklist

API key stored in environment variables or a secret manager
Key never shipped in browser or mobile-app code
Know where every integration reads the key from before regenerating it
401 responses monitored and alerted
HTTPS used for every API call
Proxy credentials kept out of logs and error reports

Next: Proxy Configuration

Gateways, rotation, sticky sessions, and geo-targeting for every proxy type.

Proxy Configuration