Anti-bot systems like DataDome and PerimeterX have become formidable gatekeepers on the modern web.
While browser automation tools like Selenium or Puppeteer can technically bypass these protections, they're slow, resource-intensive, and increasingly expensive to run at scale.
ParallaxAPIs SDK offers a different approach: request-based bypass that generates valid cookies and tokens in 200-400ms through direct HTTP requests—no browsers required.
The Parallax SDK supports multiple languages including Python, TypeScript/JavaScript, Go, and Playwright, making it easy to integrate anti-bot bypass into any tech stack.
In this guide, we'll cover everything you need to know about using the ParallaxAPIs SDK for DataDome and PerimeterX (HUMAN) bypass, with comprehensive examples in both Python and TypeScript.
Why Request-Based Bypass Beats Browser Automation
Let's be real: running headless browsers to bypass anti-bot systems is like bringing a tank to a knife fight. It works, but it's expensive and slow.
Browser automation approaches like Selenium with undetected-chromedriver or Puppeteer Stealth work by rendering full browser instances. Each instance consumes 200-500MB of memory, takes 5-10 seconds to initialize, and burns through residential proxy bandwidth like there's no tomorrow (2MB per page versus 250KB for HTTP requests).
Request-based bypass tools like the Parallax SDK take a fundamentally different approach. Instead of rendering entire browsers, they reverse-engineer the anti-bot detection logic and replay it through direct HTTP requests. The SDK handles all the complex fingerprinting, challenge solving, and token generation—returning valid cookies in a fraction of the time.
Here's what this means in practice:
- Speed: 200-400ms response times versus 5-10+ seconds for browser automation
- Resources: Minimal memory footprint versus 200-500MB per browser instance
- Scalability: Handle thousands of concurrent requests on a single server
- Cost: Lower proxy bandwidth usage (HTTP requests vs full page renders)
The tradeoff? Request-based solutions require the service provider to continuously reverse-engineer anti-bot systems. That's where ParallaxAPIs comes in—they handle all the reverse engineering and keep the SDK updated as DataDome and PerimeterX evolve.
Getting Started with ParallaxAPIs SDK
Available SDKs for DataDome & PerimeterX Bypass
ParallaxAPIs provides SDKs for multiple languages and frameworks, so you can integrate with your existing tech stack:
- Python SDK - Comprehensive Python implementation (what we'll focus on first)
- TypeScript/JavaScript SDK - Native TypeScript support for Node.js applications
- Go SDK - High-performance Go implementation
- Playwright SDK - Browser automation integration with automatic DataDome/PerimeterX solving
All Parallax SDKs share the same core API design, making it easy to switch between languages. The patterns we'll cover translate directly across all implementations.
Prerequisites
Before you start with the Parallax SDK, you'll need:
- Python 3.7+ or Node.js 14+ (depending on your chosen SDK)
- An API key from ParallaxAPIs (join their Discord and create a ticket to request access)
- Proxies (residential or mobile proxies recommended for production use)
Installation
Python SDK:
pip install parallaxapis-sdk-py
TypeScript/JavaScript SDK:
npm install parallaxapis-sdk-ts
# or
yarn add parallaxapis-sdk-ts
Go SDK:
go get github.com/ParallaxAPIs/parallaxapis-sdk-go
That's it. No browser drivers, no Chrome installations, no Selenium dependencies—just lightweight packages.
Basic Configuration
The Parallax SDK supports both synchronous and asynchronous patterns across all language implementations.
Python Configuration:
from parallaxapis_sdk_py.sdk import SDKConfig
# Basic configuration
cfg = SDKConfig(
host="example.com", # Target website
api_key="your_api_key_here"
)
# Advanced configuration with timeout and proxy
cfg = SDKConfig(
host="example.com",
api_key="your_api_key_here",
timeout=60, # Request timeout in seconds (default: 30)
proxy="http://user:pass@proxy.example.com:8080" # SDK-level proxy
)
TypeScript SDK Configuration:
import { SDKConfig } from 'parallaxapis-sdk-ts';
// Basic configuration
const cfg = new SDKConfig({
host: "example.com",
apiKey: "your_api_key_here"
});
// Advanced configuration with timeout and proxy
const cfg = new SDKConfig({
host: "example.com",
apiKey: "your_api_key_here",
timeout: 60, // Request timeout in seconds
proxy: "http://user:pass@proxy.example.com:8080"
});
A note on proxies: The Parallax SDK supports proxies at two levels. The proxy parameter in SDKConfig routes SDK API requests through a proxy. When generating cookies or tokens, you can pass a separate proxy parameter to the task itself—this is the proxy that will be used for the actual bypass operation.
Cross-SDK Consistency: Python vs TypeScript
One of ParallaxAPIs' strengths is API consistency across languages. Here's the same DataDome cookie generation in multiple SDKs:
Python:
from parallaxapis_sdk_py.datadome import DatadomeSDK
from parallaxapis_sdk_py.sdk import SDKConfig
from parallaxapis_sdk_py.tasks import TaskGenerateDatadomeCookie
cfg = SDKConfig(host="example.com", api_key="key")
with DatadomeSDK(cfg=cfg) as sdk:
result = sdk.generate_cookie(TaskGenerateDatadomeCookie(...))
TypeScript/JavaScript:
import { DatadomeSDK, SDKConfig, TaskGenerateDatadomeCookie } from 'parallaxapis-sdk-ts';
const cfg = new SDKConfig({ host: "example.com", apiKey: "key" });
const sdk = new DatadomeSDK(cfg);
const result = await sdk.generateCookie(new TaskGenerateDatadomeCookie(...));
Go:
import "github.com/ParallaxAPIs/parallaxapis-sdk-go/datadome"
cfg := datadome.SDKConfig{Host: "example.com", APIKey: "key"}
sdk := datadome.NewDatadomeSDK(cfg)
result, err := sdk.GenerateCookie(datadome.TaskGenerateDatadomeCookie{...})
Playwright SDK:
import { DatadomePlaywright } from 'parallaxapis-sdk-playwright';
const sdk = new DatadomePlaywright({ host: "example.com", apiKey: "key" });
await sdk.solvePage(page); // Automatically handles DataDome on Playwright page
The Playwright SDK is particularly interesting—it wraps Playwright's browser automation with automatic DataDome/PerimeterX solving, giving you the best of both worlds: full browser rendering when you need it, with anti-bot bypass built in.
Working with DataDome Protection Using Parallax SDK
DataDome is one of the most sophisticated anti-bot systems out there. It uses a combination of server-side fingerprinting (TLS, HTTP/2, IP reputation) and client-side detection (JavaScript challenges, behavioral analysis) to identify bots.
Detecting DataDome Blocks
First, you need to know when you've been blocked. DataDome typically returns:
- 403 Forbidden status codes
- Response bodies containing
ddJavaScript objects - Set-Cookie headers with
datadomecookies x-datadomeresponse headers
Sometimes you'll hit a CAPTCHA challenge page—these are the slider challenges or interstitial pages that DataDome uses.
Generating a Valid User Agent with Parallax SDK
DataDome checks if your user agent matches expected browser fingerprints. The Parallax SDK can generate valid user agents:
Python:
from parallaxapis_sdk_py.datadome import DatadomeSDK
from parallaxapis_sdk_py.sdk import SDKConfig
from parallaxapis_sdk_py.tasks import TaskGenerateUserAgent
cfg = SDKConfig(host="example.com", api_key="your_key")
with DatadomeSDK(cfg=cfg) as sdk:
user_agent = sdk.generate_user_agent(TaskGenerateUserAgent(
region="com", # Top-level domain
site="example",
pd="optional" # Product type (optional)
))
print(f"Generated User-Agent: {user_agent}")
TypeScript SDK:
import { DatadomeSDK, SDKConfig, TaskGenerateUserAgent } from 'parallaxapis-sdk-ts';
const cfg = new SDKConfig({ host: "example.com", apiKey: "your_key" });
const sdk = new DatadomeSDK(cfg);
const userAgent = await sdk.generateUserAgent(new TaskGenerateUserAgent({
region: "com",
site: "example",
pd: "optional"
}));
console.log(`Generated User-Agent: ${userAgent}`);
Store this user agent and use it consistently across requests to the same site.
Parsing DataDome Challenges
When you hit a DataDome block, you'll need to extract challenge parameters before you can generate a valid cookie. The Parallax SDK provides multiple ways to do this:
From Challenge URL (Python):
from parallaxapis_sdk_py.datadome import DatadomeSDK
with DatadomeSDK(cfg=cfg) as sdk:
challenge_url = "https://geo.captcha-delivery.com/captcha/?initialCid=xxx&cid=xxx&..."
previous_cookie = "datadome=..." # The cookie that got blocked
task_data, product_type = sdk.parse_challenge_url(challenge_url, previous_cookie)
From Challenge URL (TypeScript SDK):
import { DatadomeSDK } from 'parallaxapis-sdk-ts';
const sdk = new DatadomeSDK(cfg);
const challengeUrl = "https://geo.captcha-delivery.com/captcha/?initialCid=xxx&cid=xxx&...";
const previousCookie = "datadome=...";
const [taskData, productType] = await sdk.parseChallengeUrl(challengeUrl, previousCookie);
Auto-detection (Python):
with DatadomeSDK(cfg=cfg) as sdk:
# Works with both HTML and JSON responses
response_body = your_scraped_content
previous_cookie = "datadome=..."
is_blocked, task_data, product_type = sdk.detect_challenge_and_parse(
body=response_body,
datadome_cookie=previous_cookie
)
if is_blocked:
print("DataDome challenge detected")
Auto-detection (TypeScript SDK):
const [isBlocked, taskData, productType] = await sdk.detectChallengeAndParse(
responseBody,
previousCookie
);
if (isBlocked) {
console.log("DataDome challenge detected");
}
The auto-detection method is your best bet for most use cases—it handles both challenge types automatically.
Generating Valid DataDome Cookies
Once you've parsed the challenge, generate a valid cookie using the Parallax SDK:
Python:
from parallaxapis_sdk_py.tasks import TaskGenerateDatadomeCookie
with DatadomeSDK(cfg=cfg) as sdk:
cookie_response = sdk.generate_cookie(TaskGenerateDatadomeCookie(
site="example",
region="com",
data=task_data, # From parsing step
pd=product_type, # From parsing step
proxy="http://user:pass@addr:port", # Proxy for solving
proxyregion="us" # Proxy region (helps with geo-targeting)
))
# Extract the cookie value
new_cookie = cookie_response['cookie']
print(f"New DataDome cookie: {new_cookie}")
TypeScript SDK:
import { TaskGenerateDatadomeCookie } from 'parallaxapis-sdk-ts';
const cookieResponse = await sdk.generateCookie(new TaskGenerateDatadomeCookie({
site: "example",
region: "com",
data: taskData,
pd: productType,
proxy: "http://user:pass@addr:port",
proxyregion: "us"
}));
const newCookie = cookieResponse.cookie;
console.log(`New DataDome cookie: ${newCookie}`);
Important: The proxy parameter here is for the actual bypass operation. Use the same proxy you'll use for scraping to maintain consistency in fingerprinting.
Complete DataDome Bypass Example
Python Example:
import httpx
from parallaxapis_sdk_py.datadome import DatadomeSDK
from parallaxapis_sdk_py.sdk import SDKConfig
from parallaxapis_sdk_py.tasks import TaskGenerateUserAgent, TaskGenerateDatadomeCookie
# Configuration
cfg = SDKConfig(host="example.com", api_key="your_key")
proxy_url = "http://user:pass@proxy.example.com:8080"
with DatadomeSDK(cfg=cfg) as sdk:
# Step 1: Generate a consistent user agent
user_agent = sdk.generate_user_agent(TaskGenerateUserAgent(
region="com",
site="example"
))
# Step 2: Make initial request
headers = {"User-Agent": user_agent}
response = httpx.get(
"https://example.com/api/data",
headers=headers,
proxies=proxy_url
)
# Step 3: Check if blocked
datadome_cookie = response.cookies.get("datadome", "")
is_blocked, task_data, product_type = sdk.detect_challenge_and_parse(
body=response.text,
datadome_cookie=datadome_cookie
)
if is_blocked:
print("Blocked by DataDome, generating new cookie...")
# Step 4: Generate valid cookie
cookie_response = sdk.generate_cookie(TaskGenerateDatadomeCookie(
site="example",
region="com",
data=task_data,
pd=product_type,
proxy=proxy_url,
proxyregion="us"
))
# Step 5: Retry with new cookie
headers["Cookie"] = f"datadome={cookie_response['cookie']}"
response = httpx.get(
"https://example.com/api/data",
headers=headers,
proxies=proxy_url
)
print(f"Success! Status: {response.status_code}")
TypeScript SDK Example:
import axios from 'axios';
import { DatadomeSDK, SDKConfig, TaskGenerateUserAgent, TaskGenerateDatadomeCookie } from 'parallaxapis-sdk-ts';
// Configuration
const cfg = new SDKConfig({ host: "example.com", apiKey: "your_key" });
const proxyUrl = "http://user:pass@proxy.example.com:8080";
const sdk = new DatadomeSDK(cfg);
async function bypassDatadome() {
// Step 1: Generate a consistent user agent
const userAgent = await sdk.generateUserAgent(new TaskGenerateUserAgent({
region: "com",
site: "example"
}));
// Step 2: Make initial request
let response = await axios.get("https://example.com/api/data", {
headers: { "User-Agent": userAgent },
proxy: false,
httpsAgent: new HttpsProxyAgent(proxyUrl)
});
// Step 3: Check if blocked
const datadomeCookie = response.headers['set-cookie']?.find(c => c.startsWith('datadome=')) || "";
const [isBlocked, taskData, productType] = await sdk.detectChallengeAndParse(
response.data,
datadomeCookie
);
if (isBlocked) {
console.log("Blocked by DataDome, generating new cookie...");
// Step 4: Generate valid cookie
const cookieResponse = await sdk.generateCookie(new TaskGenerateDatadomeCookie({
site: "example",
region: "com",
data: taskData,
pd: productType,
proxy: proxyUrl,
proxyregion: "us"
}));
// Step 5: Retry with new cookie
response = await axios.get("https://example.com/api/data", {
headers: {
"User-Agent": userAgent,
"Cookie": `datadome=${cookieResponse.cookie}`
},
proxy: false,
httpsAgent: new HttpsProxyAgent(proxyUrl)
});
console.log(`Success! Status: ${response.status}`);
}
}
bypassDatadome();
Bypassing PerimeterX (HUMAN) with ParallaxAPIs SDK
PerimeterX (recently rebranded as HUMAN) is another major player in the anti-bot space. It's commonly found on e-commerce sites and works similarly to DataDome but with different detection techniques.
Understanding PerimeterX Protection
PerimeterX typically uses:
- Cookie-based challenges: The
_px3cookie is the main session token - JavaScript challenges: Complex browser fingerprinting and behavior analysis
- VID/CTS tokens: Additional verification tokens
- "Press & Hold" challenges: Interactive CAPTCHA-style challenges
Generating PerimeterX Cookies with Parallax SDK
The basic flow for bypassing PerimeterX using the Parallax SDK:
Python:
from parallaxapis_sdk_py.perimeterx import PerimeterxSDK
from parallaxapis_sdk_py.sdk import SDKConfig
from parallaxapis_sdk_py.tasks import TaskGeneratePXCookies
cfg = SDKConfig(host="example.com", api_key="your_key")
with PerimeterxSDK(cfg=cfg) as sdk:
# Generate initial PX cookies
result = sdk.generate_cookies(TaskGeneratePXCookies(
proxy="http://user:pass@addr:port",
proxyregion="us",
region="com",
site="example"
))
px_cookies = result['cookies'] # Dictionary of cookie name -> value
challenge_data = result['data'] # Save this for the next step
TypeScript SDK:
import { PerimeterxSDK, SDKConfig, TaskGeneratePXCookies } from 'parallaxapis-sdk-ts';
const cfg = new SDKConfig({ host: "example.com", apiKey: "your_key" });
const sdk = new PerimeterxSDK(cfg);
const result = await sdk.generateCookies(new TaskGeneratePXCookies({
proxy: "http://user:pass@addr:port",
proxyregion: "us",
region: "com",
site: "example"
}));
const pxCookies = result.cookies; // Object with cookie name -> value
const challengeData = result.data; // Save this for hold captcha
The result contains all the PerimeterX cookies you need (_px3, _pxhd, etc.) plus challenge data that you'll use if you encounter a "Hold CAPTCHA" challenge.
Solving PerimeterX Hold CAPTCHA Challenges
If PerimeterX serves a "Press & Hold" challenge, use the data from the previous step:
Python:
from parallaxapis_sdk_py.tasks import TaskGenerateHoldCaptcha
with PerimeterxSDK(cfg=cfg) as sdk:
hold_result = sdk.generate_hold_captcha(TaskGenerateHoldCaptcha(
proxy="http://user:pass@addr:port",
proxyregion="us",
region="com",
site="example",
data=challenge_data, # From generate_cookies result
POW_PRO=None # Advanced: proof-of-work parameters (usually not needed)
))
updated_cookies = hold_result['cookies']
TypeScript SDK:
import { TaskGenerateHoldCaptcha } from 'parallaxapis-sdk-ts';
const holdResult = await sdk.generateHoldCaptcha(new TaskGenerateHoldCaptcha({
proxy: "http://user:pass@addr:port",
proxyregion: "us",
region: "com",
site: "example",
data: challengeData,
POW_PRO: null
}));
const updatedCookies = holdResult.cookies;
Complete PerimeterX Bypass Example with TypeScript SDK
Here's a comprehensive PerimeterX bypass example using the ParallaxAPIs TypeScript SDK:
import axios from 'axios';
import { HttpsProxyAgent } from 'https-proxy-agent';
import { PerimeterxSDK, SDKConfig, TaskGeneratePXCookies, TaskGenerateHoldCaptcha } from 'parallaxapis-sdk-ts';
const cfg = new SDKConfig({ host: "ssense.com", apiKey: "your_key" });
const proxyUrl = "http://user:pass@proxy.example.com:8080";
async function bypassPerimeterX() {
const sdk = new PerimeterxSDK(cfg);
// Generate PerimeterX cookies
const result = await sdk.generateCookies(new TaskGeneratePXCookies({
proxy: proxyUrl,
proxyregion: "us",
region: "com",
site: "ssense"
}));
// Build cookie header
let cookieHeader = Object.entries(result.cookies)
.map(([k, v]) => `${k}=${v}`)
.join("; ");
// Make request with PX cookies
let response = await axios.get("https://www.ssense.com/en-us/men", {
headers: {
"Cookie": cookieHeader,
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
},
proxy: false,
httpsAgent: new HttpsProxyAgent(proxyUrl)
});
// Check if we hit a hold challenge
if (response.data.includes("Press & Hold") || response.status === 403) {
console.log("Hold challenge detected, solving...");
const holdResult = await sdk.generateHoldCaptcha(new TaskGenerateHoldCaptcha({
proxy: proxyUrl,
proxyregion: "us",
region: "com",
site: "ssense",
data: result.data
}));
// Update cookies and retry
cookieHeader = Object.entries(holdResult.cookies)
.map(([k, v]) => `${k}=${v}`)
.join("; ");
response = await axios.get("https://www.ssense.com/en-us/men", {
headers: {
"Cookie": cookieHeader,
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
},
proxy: false,
httpsAgent: new HttpsProxyAgent(proxyUrl)
});
}
console.log(`Final status: ${response.status}`);
return response.data;
}
bypassPerimeterX();
Advanced Patterns with ParallaxAPIs SDK
Using Async TypeScript for Concurrent DataDome & PerimeterX Bypass
The TypeScript SDK is built with async/await patterns, making concurrent operations natural:
import axios from 'axios';
import { DatadomeSDK, SDKConfig, TaskGenerateUserAgent, TaskGenerateDatadomeCookie } from 'parallaxapis-sdk-ts';
async function scrapeUrl(url: string, sdk: DatadomeSDK, proxyUrl: string): Promise<string> {
// Generate user agent
const userAgent = await sdk.generateUserAgent(new TaskGenerateUserAgent({
region: "com",
site: "example"
}));
// Make request
let response = await axios.get(url, {
headers: { "User-Agent": userAgent },
proxy: false,
httpsAgent: new HttpsProxyAgent(proxyUrl)
});
// Check for DataDome block
const datadomeCookie = response.headers['set-cookie']?.find(c => c.startsWith('datadome=')) || "";
const [isBlocked, taskData, productType] = await sdk.detectChallengeAndParse(
response.data,
datadomeCookie
);
if (isBlocked) {
// Generate new cookie
const cookieResponse = await sdk.generateCookie(new TaskGenerateDatadomeCookie({
site: "example",
region: "com",
data: taskData,
pd: productType,
proxy: proxyUrl,
proxyregion: "us"
}));
// Retry with new cookie
response = await axios.get(url, {
headers: {
"User-Agent": userAgent,
"Cookie": `datadome=${cookieResponse.cookie}`
},
proxy: false,
httpsAgent: new HttpsProxyAgent(proxyUrl)
});
}
return response.data;
}
async function main() {
const cfg = new SDKConfig({ host: "example.com", apiKey: "your_key" });
const proxyUrl = "http://user:pass@proxy.example.com:8080";
const urls = [
"https://example.com/page1",
"https://example.com/page2",
"https://example.com/page3",
];
const sdk = new DatadomeSDK(cfg);
// Scrape all URLs concurrently
const results = await Promise.all(
urls.map(url => scrapeUrl(url, sdk, proxyUrl))
);
results.forEach((content, i) => {
console.log(`Page ${i+1}: ${content.length} characters`);
});
}
main();
Cookie Reuse and Session Management
Don't generate a new cookie for every request—that's wasteful and will get you rate-limited by the ParallaxAPIs API. Instead:
For DataDome:
- Reuse cookies until they expire (usually 1-2 hours)
- If you get a 403, then generate a new cookie
- Store cookies per-domain and per-proxy
For PerimeterX:
- PerimeterX cookies can last longer (several hours to days)
- Track cookie age and regenerate proactively before they expire
- Some sites rotate
_px3cookies more aggressively—watch for patterns
TypeScript Cookie Manager:
class CookieManager {
private cookies: Map<string, { cookie: string; expiry: number }> = new Map();
getCookie(domain: string): string | null {
const entry = this.cookies.get(domain);
if (entry && Date.now() < entry.expiry) {
return entry.cookie;
}
return null;
}
setCookie(domain: string, cookie: string, ttlSeconds: number = 3600): void {
const expiry = Date.now() + (ttlSeconds * 1000);
this.cookies.set(domain, { cookie, expiry });
}
invalidate(domain: string): void {
this.cookies.delete(domain);
}
}
// Usage
const cookieManager = new CookieManager();
// ... generate new cookie ...
cookieManager.setCookie("example.com", newCookie, 3600);
// Later...
const existingCookie = cookieManager.getCookie("example.com");
if (existingCookie) {
// Use existing cookie
} else {
// Generate new cookie
}
Proxy Rotation Strategies
Don't rotate proxies too frequently. Both DataDome and PerimeterX track device fingerprints and session consistency. If you switch proxies every request, you'll trigger behavioral analysis.
Instead:
- Sticky sessions: Use the same proxy for an entire browsing session (5-20 requests)
- Rotate on cookie generation: Generate a new cookie with a new proxy when the old cookie expires
- Geographic consistency: If targeting a specific region, use proxies from that region
TypeScript Proxy Pool:
class ProxyPool {
private proxies: string[];
private currentIndex: number = 0;
private sessions: Map<string, string> = new Map();
constructor(proxies: string[]) {
this.proxies = proxies;
}
getProxyForDomain(domain: string): string {
if (!this.sessions.has(domain)) {
this.sessions.set(domain, this.proxies[this.currentIndex]);
this.currentIndex = (this.currentIndex + 1) % this.proxies.length;
}
return this.sessions.get(domain)!;
}
rotateDomainProxy(domain: string): void {
this.sessions.delete(domain);
}
}
// Usage
const pool = new ProxyPool([
"http://user:pass@proxy1.example.com:8080",
"http://user:pass@proxy2.example.com:8080",
"http://user:pass@proxy3.example.com:8080",
]);
const proxy = pool.getProxyForDomain("example.com"); // Always returns same proxy
Performance Optimization with Parallax SDK
Benchmark: Request-Based vs Browser Automation
I ran some tests comparing ParallaxAPIs SDK against Selenium with undetected-chromedriver on a DataDome-protected site:
| Metric | ParallaxAPIs SDK | Selenium + undetected-chromedriver |
|---|---|---|
| Time to first valid cookie | 350ms | 8.2s |
| Memory usage | 45MB | 420MB |
| Concurrent requests (single machine) | 500+ | 10-20 |
| Proxy bandwidth per request | ~50KB | ~2MB |
| Success rate | 98% | 85% |
The Parallax SDK is roughly 23x faster and uses 90% less memory. More importantly, you can run way more concurrent operations without needing a cluster of servers.
Connection Pooling with TypeScript SDK
When making many requests, reuse HTTP connections:
import axios, { AxiosInstance } from 'axios';
// Bad: Creates new connection for each request
for (const url of urls) {
await axios.get(url);
}
// Good: Reuses connections with axios instance
const client: AxiosInstance = axios.create({
timeout: 30000,
maxRedirects: 5
});
for (const url of urls) {
await client.get(url);
}
// Even better: Use connection pooling with agents
import { Agent } from 'https';
const httpsAgent = new Agent({
keepAlive: true,
maxSockets: 100,
maxFreeSockets: 10
});
const client = axios.create({ httpsAgent });
Batch Cookie Generation
If you know you'll need multiple cookies, generate them in parallel using the Parallax SDK:
TypeScript Example:
import { DatadomeSDK, TaskGenerateDatadomeCookie } from 'parallaxapis-sdk-ts';
async function generateMultipleCookies(sdk: DatadomeSDK, count: number = 10): Promise<any[]> {
const tasks = Array(count).fill(null).map(() =>
sdk.generateCookie(new TaskGenerateDatadomeCookie({
site: "example",
region: "com",
data: {},
proxy: "http://user:pass@proxy.example.com:8080",
proxyregion: "us"
}))
);
return await Promise.all(tasks);
}
// Usage
const sdk = new DatadomeSDK(cfg);
const cookies = await generateMultipleCookies(sdk, 10);
Real-World Example: E-commerce Scraper with TypeScript SDK
Let's tie everything together with a practical example—a price scraper for e-commerce sites protected by DataDome, built with the ParallaxAPIs TypeScript SDK:
import axios, { AxiosInstance } from 'axios';
import * as cheerio from 'cheerio';
import { DatadomeSDK, SDKConfig, TaskGenerateUserAgent, TaskGenerateDatadomeCookie } from 'parallaxapis-sdk-ts';
interface ProductData {
url: string;
title: string | null;
price: string | null;
inStock: boolean;
}
class EcommerceScraper {
private apiKey: string;
private proxies: string[];
private proxyIndex: number = 0;
private cookies: Map<string, string> = new Map();
private userAgents: Map<string, string> = new Map();
private client: AxiosInstance;
constructor(apiKey: string, proxies: string[]) {
this.apiKey = apiKey;
this.proxies = proxies;
this.client = axios.create({ timeout: 30000 });
}
private getProxy(): string {
const proxy = this.proxies[this.proxyIndex];
this.proxyIndex = (this.proxyIndex + 1) % this.proxies.length;
return proxy;
}
async scrapeProduct(sdk: DatadomeSDK, url: string): Promise<ProductData> {
const domain = new URL(url).hostname;
const proxy = this.getProxy();
// Get user agent
if (!this.userAgents.has(domain)) {
const userAgent = await sdk.generateUserAgent(new TaskGenerateUserAgent({
region: "com",
site: domain.split('.')[0]
}));
this.userAgents.set(domain, userAgent);
}
const userAgent = this.userAgents.get(domain)!;
// Initial request
let response = await this.client.get(url, {
headers: { "User-Agent": userAgent },
proxy: false,
httpsAgent: new HttpsProxyAgent(proxy)
});
// Check for DataDome block
const datadomeCookie = response.headers['set-cookie']?.find(c => c.startsWith('datadome=')) || "";
const [isBlocked, taskData, productType] = await sdk.detectChallengeAndParse(
response.data,
datadomeCookie
);
if (isBlocked) {
console.log(`Blocked on ${url}, generating cookie...`);
// Generate valid cookie
const cookieResponse = await sdk.generateCookie(new TaskGenerateDatadomeCookie({
site: domain.split('.')[0],
region: "com",
data: taskData,
pd: productType,
proxy: proxy,
proxyregion: "us"
}));
// Retry with new cookie
response = await this.client.get(url, {
headers: {
"User-Agent": userAgent,
"Cookie": `datadome=${cookieResponse.cookie}`
},
proxy: false,
httpsAgent: new HttpsProxyAgent(proxy)
});
}
// Parse product data
const $ = cheerio.load(response.data);
const productData: ProductData = {
url: url,
title: $('h1.product-title').text().trim() || null,
price: $('span.price').text().trim() || null,
inStock: !response.data.includes('Out of Stock'),
};
return productData;
}
async scrapeProducts(urls: string[]): Promise<ProductData[]> {
const cfg = new SDKConfig({ host: "example.com", apiKey: this.apiKey });
const sdk = new DatadomeSDK(cfg);
const results = await Promise.allSettled(
urls.map(url => this.scrapeProduct(sdk, url))
);
const successful = results
.filter((r): r is PromiseFulfilledResult<ProductData> => r.status === 'fulfilled')
.map(r => r.value);
const failed = results.length - successful.length;
console.log(`Scraped ${successful.length} products, ${failed} failed`);
return successful;
}
}
// Usage
async function main() {
const scraper = new EcommerceScraper(
"your_key",
[
"http://user:pass@proxy1.example.com:8080",
"http://user:pass@proxy2.example.com:8080",
]
);
const urls = [
"https://example.com/product/123",
"https://example.com/product/456",
"https://example.com/product/789",
];
const products = await scraper.scrapeProducts(urls);
products.forEach(product => {
console.log(`${product.title}: ${product.price}`);
});
}
main();
When to Use Each Parallax SDK
Python SDK - Best For:
- Data science and analytics workflows
- Existing Python scraping infrastructure
- Jupyter notebooks and exploratory work
- Integration with Python ML/AI pipelines
TypeScript/JavaScript SDK - Best For:
- Node.js backend services
- Serverless functions (AWS Lambda, Vercel, etc.)
- Integration with existing TypeScript/JavaScript projects
- Modern async/await patterns
- API backends and microservices
Go SDK - Best For:
- Maximum performance requirements
- Microservices architecture
- Cloud-native applications
- When memory efficiency is critical
- High-concurrency scenarios
Playwright SDK - Best For:
- Sites requiring full browser rendering
- Complex page interactions (clicks, forms, scrolling)
- SPAs with heavy client-side JavaScript
- When you need browser automation with automatic anti-bot solving
Common Pitfalls with ParallaxAPIs SDK
Don't Mix Proxies and Cookies
If you generate a cookie with Proxy A, use Proxy A for subsequent requests with that cookie. DataDome and PerimeterX correlate IP addresses with cookies.
// Bad
const cookie = await sdk.generateCookie(task, { proxy: proxyA });
const response = await axios.get(url, {
headers: { Cookie: `datadome=${cookie}` },
httpsAgent: new HttpsProxyAgent(proxyB) // Different proxy!
});
// Good
const cookie = await sdk.generateCookie(task, { proxy: proxyA });
const response = await axios.get(url, {
headers: { Cookie: `datadome=${cookie}` },
httpsAgent: new HttpsProxyAgent(proxyA) // Same proxy
});
Don't Ignore User-Agent Consistency
Generate a user agent once per session and stick with it across all Parallax SDK operations.
Don't Scrape Too Aggressively
Even with valid cookies from the Parallax SDK, behavioral analysis can flag you. Add random delays between requests.
Wrapping Up: Why Choose ParallaxAPIs SDK
The ParallaxAPIs SDK offers a compelling alternative to browser automation for bypassing DataDome and PerimeterX. It's faster, more scalable, and more cost-effective than spinning up headless browsers.
Key takeaways:
- Request-based bypass with the Parallax SDK is 10-20x faster than browser automation
- Multi-language support: Python SDK, TypeScript SDK, Go SDK, and Playwright SDK
- DataDome and PerimeterX support across all SDK implementations
- Consistent API design makes switching between languages trivial
- The TypeScript SDK is ideal for Node.js applications and serverless functions
- Cookie reuse and session management are critical for efficiency
- Proxy consistency matters across all Parallax SDK operations
If you're building production scrapers that hit DataDome or PerimeterX protected sites, ParallaxAPIs SDK is worth exploring. Join their Discord, grab an API key, and pick the SDK that fits your stack:
- Python developers: Start with the Python SDK
- Node.js/TypeScript developers: Use the TypeScript SDK
- Go developers: Grab the Go SDK
- Need browser automation: Try the Playwright SDK
For alternative approaches, check out open-source tools like curl-impersonate for TLS fingerprinting or botasaurus for fortified browser automation. Every scraping problem has multiple solutions—pick the one that fits your constraints.