Trying to route your Zapier webhook calls through a proxy? You’re not alone. Zapier’s webhook actions are great for sending GET, POST, or PUT requests — and they handle data parsing nicely — but when it comes to configuring a proxy, they leave you hanging.
If you’ve got proxy credentials in the typical IP:PORT:USERNAME:PASSWORD format from your proxy provider, you’ll quickly notice there’s no straightforward way to drop those details into Zapier’s webhook settings. This gap pushes developers to get a little creative to make proxy routing work.
That’s exactly what this guide is here for. I’ll walk you through four practical, battle-tested ways to use your proxies with Zapier — so your requests stay private, compliant, and reliable.
What you’ll learn:
- Why Zapier doesn’t let you add proxies out of the box
- 4 proven ways to work around that limitation
- Full code examples for each approach
- Tips for keeping your proxy credentials secure
Why RoundProxies Integration Matters
RoundProxies gives you straightforward HTTP/HTTPS proxy credentials like this:
IP:PORT:USERNAME:PASSWORD
Example: 123.45.67.89:8080:user123:pass456
Plugging these into your Zapier workflows opens up all kinds of flexibility:
- Rotate IPs: Keep your IP fresh to handle rate limits better.
- Target regions: Send requests through proxies located where you need them.
- Stay anonymous: Keep your true IP hidden from destination servers.
- Comply with rules: Make sure your traffic flows through approved regions.
Since Zapier doesn’t have built-in proxy support for webhooks, you’ll need to bridge that gap with one of these workarounds.
Step 1: Deploy an Intermediate Proxy Gateway
The most robust method is to spin up your own gateway. Think of it as a tiny API server that catches requests from Zapier and forwards them through your RoundProxies proxy.
Node.js Implementation
Create an Express server that does the forwarding for you:
const express = require('express');
const axios = require('axios');
const HttpsProxyAgent = require('https-proxy-agent');
const app = express();
app.use(express.json());
// RoundProxies credentials
const PROXY_CONFIG = {
host: '123.45.67.89',
port: 8080,
auth: {
username: 'user123',
password: 'pass456'
}
};
// Create proxy URL
const proxyUrl = `http://${PROXY_CONFIG.auth.username}:${PROXY_CONFIG.auth.password}@${PROXY_CONFIG.host}:${PROXY_CONFIG.port}`;
const httpsAgent = new HttpsProxyAgent(proxyUrl);
app.post('/forward', async (req, res) => {
try {
const { targetUrl, method = 'GET', headers = {}, data } = req.body;
// Validate required fields
if (!targetUrl) {
return res.status(400).json({ error: 'targetUrl is required' });
}
// Make request through proxy
const response = await axios({
url: targetUrl,
method,
data,
headers: {
...headers,
'X-Forwarded-By': 'Zapier-Proxy-Gateway'
},
httpsAgent,
timeout: 30000 // 30 second timeout
});
res.json({
status: response.status,
headers: response.headers,
data: response.data
});
} catch (error) {
console.error('Proxy request failed:', error.message);
res.status(error.response?.status || 500).json({
error: error.message,
details: error.response?.data
});
}
});
// Health check endpoint
app.get('/health', (req, res) => {
res.json({ status: 'ok', proxy: 'RoundProxies' });
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Proxy gateway running on port ${PORT}`);
});
Deployment Options
You have a few good options to get this up and running:
1. Heroku (Free plan available)
# Create Heroku app
heroku create your-proxy-gateway
# Deploy
git push heroku main
# Your gateway URL: https://your-proxy-gateway.herokuapp.com/forward
2. Railway.app (Super simple)
# Install Railway CLI
npm install -g @railway/cli
# Deploy
railway login
railway init
railway up
3. VPS (If you want full control)
# On your VPS
npm install pm2 -g
pm2 start app.js --name proxy-gateway
pm2 startup
pm2 save
Zapier Configuration
When you’re ready, plug your new gateway into Zapier like this:
- URL:
https://your-gateway.com/forward
- Method: POST
- Payload Type: JSON
- Data:
{
"targetUrl": "https://api.example.com/endpoint",
"method": "GET",
"headers": {
"Authorization": "Bearer YOUR_API_TOKEN"
}
}
Step 2: Build a Custom Zapier Platform App
Want a tighter Zapier integration? Then you’ll want to roll up your sleeves and build a private Zapier app that bakes proxy config right in.
Setting Up Your Private App
- Head to Zapier’s Developer Platform
- Click Start Building → Create App
- Pick Private so only you use it
Authentication Configuration
Set up your proxy details in the app’s authentication section:
// authentication.js
module.exports = {
type: 'custom',
fields: [
{
key: 'proxy_ip',
label: 'Proxy IP',
required: true,
helpText: 'Your RoundProxies IP address'
},
{
key: 'proxy_port',
label: 'Proxy Port',
required: true,
helpText: 'Your RoundProxies port number'
},
{
key: 'proxy_username',
label: 'Proxy Username',
required: true
},
{
key: 'proxy_password',
label: 'Proxy Password',
required: true,
type: 'password'
}
],
test: async (z, bundle) => {
// Test the proxy connection
const ProxyAgent = require('proxy-agent');
const proxyUrl = `http://${bundle.authData.proxy_username}:${bundle.authData.proxy_password}@${bundle.authData.proxy_ip}:${bundle.authData.proxy_port}`;
try {
const response = await z.request({
url: 'http://httpbin.org/ip',
agent: new ProxyAgent(proxyUrl)
});
return { proxy_ip: response.data.origin };
} catch (error) {
throw new Error('Proxy authentication failed');
}
}
};
Create a Generic Request Action
Here’s how your proxy request action might look:
// actions/proxyRequest.js
const ProxyAgent = require('proxy-agent');
module.exports = {
key: 'proxy_request',
noun: 'Proxy Request',
display: {
label: 'Make Proxy Request',
description: 'Send a request through RoundProxies'
},
operation: {
inputFields: [
{
key: 'url',
label: 'Target URL',
required: true,
helpText: 'The URL to send the request to'
},
{
key: 'method',
label: 'HTTP Method',
choices: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'],
default: 'GET',
required: true
},
{
key: 'headers',
label: 'Headers',
dict: true,
helpText: 'Additional headers to send'
},
{
key: 'body',
label: 'Request Body',
type: 'text',
helpText: 'JSON body for POST/PUT requests'
}
],
perform: async (z, bundle) => {
const { proxy_ip, proxy_port, proxy_username, proxy_password } = bundle.authData;
const proxyUrl = `http://${proxy_username}:${proxy_password}@${proxy_ip}:${proxy_port}`;
const agent = new ProxyAgent(proxyUrl);
const options = {
url: bundle.inputData.url,
method: bundle.inputData.method,
headers: bundle.inputData.headers || {},
agent: agent
};
if (bundle.inputData.body) {
options.body = bundle.inputData.body;
options.headers['Content-Type'] = 'application/json';
}
try {
const response = await z.request(options);
return {
status: response.status,
headers: response.headers,
data: response.data,
proxy_used: proxy_ip
};
} catch (error) {
throw new z.errors.Error(
`Proxy request failed: ${error.message}`,
'ProxyRequestFailed',
error.status
);
}
}
}
};
Why This Works
- Smooth user experience: Feels just like any other Zapier app.
- Credentials stay safe: Zapier keeps auth info secure.
- Reusable: Use it in any Zap without reconfiguring.
- Handles errors gracefully: Clear error feedback when things fail.
Step 3: Use Code by Zapier for Simple Requests
If you only need a quick, lightweight solution, Code by Zapier can do the job for simple proxy calls.
Python Implementation
# Code by Zapier - Python
import requests
from requests.auth import HTTPProxyAuth
# RoundProxies credentials
proxy_host = "123.45.67.89"
proxy_port = "8080"
proxy_user = "user123"
proxy_pass = "pass456"
# Configure proxy
proxies = {
'http': f'http://{proxy_user}:{proxy_pass}@{proxy_host}:{proxy_port}',
'https': f'http://{proxy_user}:{proxy_pass}@{proxy_host}:{proxy_port}'
}
# Make request
try:
response = requests.get(
input_data.get('url', 'http://httpbin.org/ip'),
proxies=proxies,
timeout=30,
headers={'User-Agent': 'Zapier-Proxy-Client/1.0'}
)
output = {
'status_code': response.status_code,
'data': response.json() if response.headers.get('content-type', '').startswith('application/json') else response.text,
'proxy_ip': proxy_host
}
except Exception as e:
output = {'error': str(e)}
return output
JavaScript Implementation
// Code by Zapier - JavaScript
const fetch = require('node-fetch');
const HttpsProxyAgent = require('https-proxy-agent');
// RoundProxies credentials
const proxyConfig = {
host: '123.45.67.89',
port: '8080',
username: 'user123',
password: 'pass456'
};
// Create proxy URL
const proxyUrl = `http://${proxyConfig.username}:${proxyConfig.password}@${proxyConfig.host}:${proxyConfig.port}`;
const proxyAgent = new HttpsProxyAgent(proxyUrl);
// Make request
const makeProxyRequest = async () => {
try {
const response = await fetch(inputData.url || 'http://httpbin.org/ip', {
agent: proxyAgent,
method: inputData.method || 'GET',
headers: {
'User-Agent': 'Zapier-Proxy/1.0',
...inputData.headers
},
body: inputData.body ? JSON.stringify(inputData.body) : undefined
});
const data = await response.text();
return {
statusCode: response.status,
data: data,
proxyUsed: proxyConfig.host
};
} catch (error) {
return {
error: error.message,
proxyConfig: proxyConfig.host
};
}
};
return await makeProxyRequest();
When This Makes Sense
- For quick tests or one-off calls
- When you don’t need heavy libraries
- For small payloads with short execution time
Keep in mind: Code steps have execution limits — so don’t plan anything too complex here.
Step 4: Create a Serverless Proxy Function
Want something scalable without maintaining servers? A serverless proxy is your best bet.
Vercel Edge Function
Try an edge function like this:
import fetch from 'node-fetch';
import { HttpsProxyAgent } from 'https-proxy-agent';
// Store credentials in environment variables
const PROXY_URL = `http://${process.env.PROXY_USER}:${process.env.PROXY_PASS}@${process.env.PROXY_HOST}:${process.env.PROXY_PORT}`;
export default async function handler(req, res) {
// Only allow POST requests
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' });
}
// Verify API key
const apiKey = req.headers['x-api-key'];
if (apiKey !== process.env.API_KEY) {
return res.status(401).json({ error: 'Unauthorized' });
}
const { targetUrl, method = 'GET', headers = {}, body } = req.body;
if (!targetUrl) {
return res.status(400).json({ error: 'targetUrl is required' });
}
try {
const proxyAgent = new HttpsProxyAgent(PROXY_URL);
const response = await fetch(targetUrl, {
method,
headers: {
...headers,
'X-Proxy-Client': 'Zapier-Vercel'
},
body: body ? JSON.stringify(body) : undefined,
agent: proxyAgent
});
const data = await response.text();
res.status(200).json({
status: response.status,
headers: Object.fromEntries(response.headers),
data: data,
proxy: process.env.PROXY_HOST
});
} catch (error) {
console.error('Proxy error:', error);
res.status(500).json({
error: 'Proxy request failed',
message: error.message
});
}
}
Environment Variables
Set your credentials safely in the Vercel dashboard:
PROXY_HOST=123.45.67.89
PROXY_PORT=8080
PROXY_USER=user123
PROXY_PASS=pass456
API_KEY=your-secret-api-key
Deploy to Vercel
# Install Vercel CLI
npm i -g vercel
# Deploy
vercel --prod
# Your function URL: https://your-app.vercel.app/api/proxy
Zapier Configuration
- URL:
https://your-app.vercel.app/api/proxy
- Headers:
X-API-Key
:your-secret-api-key
- Data:
{
"targetUrl": "https://api.example.com/data",
"method": "GET"
}
Common Mistakes to Avoid
1. Exposing Proxy Credentials
Don’t hardcode sensitive info directly in webhook requests.
Wrong:
// Never hardcode credentials in Zapier webhooks
const proxyUrl = "http://user123:pass456@123.45.67.89:8080"; // DON'T DO THIS
Right:
// Use environment variables or secure storage
const proxyUrl = process.env.PROXY_URL;
2. Skipping Error Handling
Wrap requests with proper try/catch
blocks. Don’t assume they’ll always succeed.
Wrong:
const response = await makeProxyRequest();
return response.data; // What if it fails?
Right:
try {
const response = await makeProxyRequest();
return { success: true, data: response.data };
} catch (error) {
return { success: false, error: error.message };
}
3. No Timeouts
Always define timeouts. It helps you avoid stuck connections.
const response = await axios({
url: targetUrl,
timeout: 30000, // 30 seconds
httpsAgent: proxyAgent
});
4. Not Validating Inputs
Always check inputs coming from Zapier.
if (!bundle.inputData.url || !bundle.inputData.url.startsWith('http')) {
throw new Error('Invalid URL provided');
}
5. Forgetting Auth
Zapier’s Basic Auth won’t help here — your intermediate layer must handle proxy auth.
Security Best Practices
Keep these points in mind to stay secure:
- Store credentials in environment variables — never in plain code.
- Always use HTTPS for requests.
- Protect serverless endpoints with API keys.
- Whitelist Zapier’s IPs if possible.
- Rotate passwords often.
- Keep an eye on logs for odd behavior.
Final Thoughts
Zapier doesn’t make proxying easy — but it’s far from impossible. Use one of these methods to push your traffic through RoundProxies:
- Quick fix: Code by Zapier for simple tasks.
- Solid solution: A proxy gateway for production.
- Native feel: A custom Zapier Platform App.
- Fully serverless: An edge function for scale.
For most cases, a simple proxy gateway strikes the best balance between easy setup and rock-solid reliability.