Can I Use Rotating Proxies with n8n Workflows?
Yes, you can use rotating proxies with n8n workflows to enhance your web scraping operations, avoid IP bans, and distribute requests across multiple IP addresses. While n8n doesn't have a built-in proxy rotation system, you can implement rotating proxies through several approaches including custom code nodes, external proxy services, and HTTP request configurations.
Why Use Rotating Proxies in n8n?
Rotating proxies are essential for professional web scraping workflows because they:
- Prevent IP blocking: Distributing requests across multiple IPs reduces the chance of being blocked
- Bypass rate limits: Different IPs allow you to make more requests without triggering anti-bot measures
- Access geo-restricted content: Use proxies from different locations to access region-specific data
- Improve reliability: If one proxy fails, your workflow can continue with another
- Scale scraping operations: Handle higher volumes of requests without detection
Method 1: Using Proxy Lists with HTTP Request Nodes
The simplest approach is to maintain a list of proxies and rotate through them using n8n's native functionality.
Setting Up a Proxy List
First, create a function node to manage your proxy list:
// Function Node: Get Next Proxy
const proxies = [
'http://proxy1.example.com:8080',
'http://proxy2.example.com:8080',
'http://proxy3.example.com:8080',
'http://proxy4.example.com:8080'
];
// Get workflow execution ID to determine which proxy to use
const executionId = $execution.id;
const proxyIndex = executionId % proxies.length;
return {
json: {
proxy: proxies[proxyIndex],
proxyIndex: proxyIndex
}
};
Configuring HTTP Request with Proxy
Use the proxy in your HTTP Request node:
// In HTTP Request node, use this expression in the proxy field:
{{ $json.proxy }}
For authenticated proxies, configure the format:
const proxies = [
'http://username:password@proxy1.example.com:8080',
'http://username:password@proxy2.example.com:8080'
];
Method 2: Dynamic Proxy Rotation with Code Node
For more advanced rotation strategies, implement custom logic in a Code node:
// Code Node: Advanced Proxy Rotation
class ProxyRotator {
constructor() {
this.proxies = [
{ url: 'http://proxy1.example.com:8080', failures: 0, lastUsed: 0 },
{ url: 'http://proxy2.example.com:8080', failures: 0, lastUsed: 0 },
{ url: 'http://proxy3.example.com:8080', failures: 0, lastUsed: 0 }
];
this.maxFailures = 3;
}
getNextProxy() {
// Filter out failed proxies
const availableProxies = this.proxies.filter(
p => p.failures < this.maxFailures
);
if (availableProxies.length === 0) {
throw new Error('No available proxies');
}
// Get least recently used proxy
const proxy = availableProxies.sort((a, b) => a.lastUsed - b.lastUsed)[0];
proxy.lastUsed = Date.now();
return proxy.url;
}
markFailure(proxyUrl) {
const proxy = this.proxies.find(p => p.url === proxyUrl);
if (proxy) {
proxy.failures++;
}
}
markSuccess(proxyUrl) {
const proxy = this.proxies.find(p => p.url === proxyUrl);
if (proxy) {
proxy.failures = Math.max(0, proxy.failures - 1);
}
}
}
// Initialize rotator (use workflow static data to persist)
const rotator = new ProxyRotator();
const nextProxy = rotator.getNextProxy();
return {
json: {
proxy: nextProxy,
timestamp: Date.now()
}
};
Method 3: Using Puppeteer/Playwright with Proxies
When working with headless browsers in n8n, you can configure proxies for handling browser sessions more effectively:
// Puppeteer node with proxy configuration
const puppeteer = require('puppeteer');
const proxies = [
'http://proxy1.example.com:8080',
'http://proxy2.example.com:8080'
];
const currentProxy = proxies[Math.floor(Math.random() * proxies.length)];
const browser = await puppeteer.launch({
args: [
`--proxy-server=${currentProxy}`,
'--no-sandbox',
'--disable-setuid-sandbox'
]
});
const page = await browser.newPage();
// Authenticate if needed
if (currentProxy.includes('@')) {
const [credentials, host] = currentProxy.split('@');
const [username, password] = credentials.replace('http://', '').split(':');
await page.authenticate({
username: username,
password: password
});
}
await page.goto('https://example.com');
const content = await page.content();
await browser.close();
return { json: { content } };
Method 4: Integration with External Proxy Services
Many commercial proxy services offer API endpoints that automatically rotate proxies. Here's how to integrate them:
// Using WebScrapingAPI or similar services with built-in rotation
const axios = require('axios');
const response = await axios.get('https://api.webscraping.ai/html', {
params: {
api_key: 'YOUR_API_KEY',
url: 'https://target-website.com',
proxy: 'datacenter', // or 'residential' for rotating proxies
country: 'us'
}
});
return { json: response.data };
Using Bright Data (Luminati) Proxy Service
// Code Node: Bright Data Rotating Proxy
const axios = require('axios');
const brightDataConfig = {
host: 'zproxy.lum-superproxy.io',
port: 22225,
username: 'lum-customer-YOUR_CUSTOMER_ID-zone-YOUR_ZONE',
password: 'YOUR_PASSWORD'
};
const proxyUrl = `http://${brightDataConfig.username}:${brightDataConfig.password}@${brightDataConfig.host}:${brightDataConfig.port}`;
const response = await axios.get('https://target-website.com', {
proxy: {
host: brightDataConfig.host,
port: brightDataConfig.port,
auth: {
username: brightDataConfig.username,
password: brightDataConfig.password
}
}
});
return { json: response.data };
Method 5: Webhook-Based Proxy Rotation
Create an external microservice that handles proxy rotation and call it from n8n:
# External Python Flask service for proxy rotation
from flask import Flask, jsonify, request
import random
import time
app = Flask(__name__)
PROXY_POOL = [
'http://proxy1.example.com:8080',
'http://proxy2.example.com:8080',
'http://proxy3.example.com:8080'
]
proxy_stats = {proxy: {'requests': 0, 'last_used': 0} for proxy in PROXY_POOL}
@app.route('/get-proxy', methods=['GET'])
def get_proxy():
# Simple round-robin with cooldown
available = [
p for p in PROXY_POOL
if time.time() - proxy_stats[p]['last_used'] > 5
]
if not available:
available = PROXY_POOL
proxy = random.choice(available)
proxy_stats[proxy]['requests'] += 1
proxy_stats[proxy]['last_used'] = time.time()
return jsonify({
'proxy': proxy,
'stats': proxy_stats[proxy]
})
if __name__ == '__main__':
app.run(port=5000)
Call this service from n8n using an HTTP Request node:
// In n8n HTTP Request node
// GET http://your-proxy-service.com/get-proxy
// Then use the returned proxy in subsequent requests
const proxyResponse = $node["Get Proxy"].json;
const targetUrl = 'https://example.com';
// Make request with the rotated proxy
// (Use in next HTTP Request node)
Best Practices for Proxy Rotation in n8n
1. Implement Retry Logic
When a proxy fails, automatically retry with a different proxy:
// Code Node: Retry with Proxy Rotation
const maxRetries = 3;
const proxies = ['proxy1.com:8080', 'proxy2.com:8080', 'proxy3.com:8080'];
for (let i = 0; i < maxRetries; i++) {
try {
const proxy = proxies[i % proxies.length];
// Make request with current proxy
const response = await makeRequest(proxy);
return { json: response };
} catch (error) {
if (i === maxRetries - 1) {
throw error; // All retries failed
}
// Wait before retry
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
2. Monitor Proxy Health
Track proxy performance and remove failing proxies:
// Store proxy health metrics
const proxyMetrics = {
'proxy1.com:8080': { success: 45, failure: 5, avgResponseTime: 1200 },
'proxy2.com:8080': { success: 48, failure: 2, avgResponseTime: 800 }
};
function getHealthyProxy() {
const healthyProxies = Object.entries(proxyMetrics)
.filter(([proxy, metrics]) => {
const successRate = metrics.success / (metrics.success + metrics.failure);
return successRate > 0.8 && metrics.avgResponseTime < 3000;
})
.map(([proxy]) => proxy);
return healthyProxies[Math.floor(Math.random() * healthyProxies.length)];
}
3. Respect Rate Limits
Add delays between requests when using network request monitoring:
// Code Node: Rate-Limited Proxy Requests
const items = $input.all();
const results = [];
const delayMs = 2000; // 2 seconds between requests
for (let i = 0; i < items.length; i++) {
const proxy = proxies[i % proxies.length];
const result = await makeRequest(items[i], proxy);
results.push(result);
// Wait before next request
if (i < items.length - 1) {
await new Promise(resolve => setTimeout(resolve, delayMs));
}
}
return results.map(r => ({ json: r }));
4. Use Workflow Static Data
Store proxy state across workflow executions:
// Access workflow static data
const staticData = this.getWorkflowStaticData('global');
if (!staticData.proxyIndex) {
staticData.proxyIndex = 0;
}
const proxies = ['proxy1', 'proxy2', 'proxy3'];
const currentProxy = proxies[staticData.proxyIndex];
// Increment for next execution
staticData.proxyIndex = (staticData.proxyIndex + 1) % proxies.length;
return { json: { proxy: currentProxy } };
Error Handling and Fallbacks
Implement robust error handling for proxy failures:
// Code Node: Proxy Error Handling
async function makeRequestWithProxyRotation(url, proxies) {
const errors = [];
for (const proxy of proxies) {
try {
const response = await axios.get(url, {
proxy: parseProxyUrl(proxy),
timeout: 10000
});
return {
success: true,
data: response.data,
proxy: proxy
};
} catch (error) {
errors.push({
proxy: proxy,
error: error.message
});
// Continue to next proxy
continue;
}
}
// All proxies failed
throw new Error(`All proxies failed: ${JSON.stringify(errors)}`);
}
function parseProxyUrl(proxyString) {
// Parse proxy string into axios proxy config
const url = new URL(proxyString);
return {
host: url.hostname,
port: parseInt(url.port),
auth: url.username ? {
username: url.username,
password: url.password
} : undefined
};
}
const result = await makeRequestWithProxyRotation(
'https://example.com',
['http://proxy1:8080', 'http://proxy2:8080']
);
return { json: result };
Conclusion
Rotating proxies are fully compatible with n8n workflows and can significantly improve your web scraping reliability and success rate. Whether you choose to implement a simple round-robin rotation with native n8n nodes, leverage external proxy services, or build custom rotation logic, the key is to monitor proxy health, implement proper error handling, and respect rate limits.
For production environments, consider using professional proxy services with built-in rotation or implementing a dedicated proxy management microservice that your n8n workflows can call. This approach provides better scalability and easier maintenance as your scraping needs grow.
When working with browser automation workflows, make sure to properly configure proxy authentication and test your setup thoroughly before deploying to production.