QuotaGuard and Zapier Integration Guide

    QuotaGuard and Zapier Integration Guide

    QuotaGuard Static IPs allow your Zapier workflows to send outbound HTTP requests through a load-balanced pair of static IP addresses. Once configured, you can use QuotaGuard’s IPs to connect to firewalled APIs, enterprise databases, and services that require IP allowlisting.

    This integration requires “Code by Zapier” steps. Standard Zap triggers and actions (like Gmail, Slack, or Webhooks by Zapier) cannot be proxied directly. QuotaGuard is specifically for custom code steps that need to reach external services requiring a known, static source IP address.

    Why Zaps Get Blocked

    Zapier runs on AWS infrastructure in the us-east-1 region, spinning up instances dynamically as needed. This means your Zap’s outbound traffic could originate from millions of potential IP addresses shared across all Zapier customers.

    When your Zap tries to connect to security-conscious partners, you’ll see errors like:

    • 403 Forbidden from corporate firewalls and WAFs
    • Connection refused from databases with IP allowlisting
    • Access denied from banking APIs and payment gateways
    • Blocked requests from Google Workspace Context-Aware Access policies

    The problem is not your code or API keys. The target service is blocking requests from unknown cloud IP ranges.

    QuotaGuard gives your Zaps a fixed, verifiable identity that partners can add to their firewall allowlists once.

    Zapier’s Native Static IP Feature

    Zapier introduced a static IP feature for Teams, Company, and Enterprise plans. Before using QuotaGuard, you should understand when Zapier’s native feature works and when you need QuotaGuard instead.

    When Zapier’s Native Static IP Works

    Zapier’s static IP feature is limited to specific enabled apps:

    • Database integrations: Redshift, BigQuery, Snowflake
    • Private integrations where the app owner has enabled static IP support
    • Some specific public apps that have opted in

    If you’re on a Teams/Company/Enterprise plan AND using one of the supported database apps, Zapier’s native static IP may work for you.

    When You Need QuotaGuard

    You need QuotaGuard when:

    • You’re using a standard or free Zapier plan
    • Your target service is not one of Zapier’s supported static IP apps
    • You need to proxy HTTP requests from Webhooks by Zapier (which has no proxy option)
    • You need to connect to custom APIs, internal services, or partners not in Zapier’s supported list
    • You need HIPAA/PCI compliance features (QuotaGuard Shield)
    • You need regional data residency (US/EU proxy selection)
    FeatureZapier Native Static IPQuotaGuard
    Plan requirementTeams/Company/EnterpriseAny plan
    Supported appsLimited (databases, private apps)Any Code by Zapier step
    Custom HTTP requestsNot supportedFully supported
    HIPAA/PCI complianceNoYes (Shield)
    Data residencyNoUS/EU options
    Dedicated IPsShared CIDR blockYour own IP pair

    Getting Started

    After creating a QuotaGuard account, you will be redirected to your dashboard where you can find your proxy credentials and static IP addresses.

    Choose the right proxy region: Zapier runs primarily in AWS us-east-1. For lowest latency, select QuotaGuard’s US-East region.

    Your proxy URL will look like this:

    http://username:password@us-east-static-01.quotaguard.com:9293
    

    This URL contains your credentials and the proxy hostname. You’ll use this to route requests through your static IPs.

    Finding Your Static IPs: Your two static IPs are displayed in the QuotaGuard dashboard. Both IPs are active simultaneously for high availability. Add both to any firewall allowlists you’re configuring on the target service side.

    Understanding Zapier’s Code Environment

    Zapier’s Code by Zapier app provides two language options:

    Python Environment

    • Python 3.7.2
    • Standard library available
    • requests library pre-installed
    • BeautifulSoup library available
    • Cannot install pip modules

    JavaScript Environment

    • Node.js 18
    • Standard Node.js library available
    • Built-in fetch available
    • Cannot install npm modules

    Important: JavaScript’s built-in fetch in Node.js 18 does not support proxy configuration. This is a known limitation of the Fetch API. To use proxies in JavaScript Code steps, you must use the raw http and https modules with the HTTP CONNECT method.

    For this reason, Python is the recommended language for proxy integration in Zapier. The requests library supports proxies natively with a simple configuration.

    Python is the simplest and most reliable way to route Zapier requests through QuotaGuard. The requests library is pre-installed and supports proxies natively.

    Basic Setup

    Step 1: In the Zap editor, click + to add a new step.

    Step 2: Search for and select Code by Zapier.

    Step 3: Select Run Python as the action.

    Step 4: In the Input Data section, add your proxy URL as a variable:

    • Key: proxy_url
    • Value: http://username:password@us-east-static-01.quotaguard.com:9293

    Using Input Data keeps your credentials out of the code itself.

    Step 5: Add your code in the Code field.

    HTTP GET Request

    import requests
    
    # Get proxy URL from Input Data
    proxy_url = input_data.get('proxy_url')
    
    # Configure proxy
    proxies = {
        'http': proxy_url,
        'https': proxy_url
    }
    
    # Make the request
    response = requests.get(
        'https://api.example.com/data',
        proxies=proxies,
        timeout=25
    )
    
    # Return the response
    output = {
        'status_code': response.status_code,
        'data': response.json()
    }
    

    HTTP POST Request with JSON

    import requests
    import json
    
    proxy_url = input_data.get('proxy_url')
    proxies = {'http': proxy_url, 'https': proxy_url}
    
    # Data to send
    payload = {
        'name': input_data.get('name'),
        'email': input_data.get('email'),
        'message': input_data.get('message')
    }
    
    response = requests.post(
        'https://api.example.com/submit',
        json=payload,
        proxies=proxies,
        headers={'Content-Type': 'application/json'},
        timeout=25
    )
    
    output = {
        'status_code': response.status_code,
        'response': response.json() if response.headers.get('content-type', '').startswith('application/json') else response.text
    }
    

    HTTP PUT Request

    import requests
    
    proxy_url = input_data.get('proxy_url')
    proxies = {'http': proxy_url, 'https': proxy_url}
    
    record_id = input_data.get('record_id')
    updated_data = {
        'status': input_data.get('status'),
        'notes': input_data.get('notes')
    }
    
    response = requests.put(
        f'https://api.example.com/records/{record_id}',
        json=updated_data,
        proxies=proxies,
        timeout=25
    )
    
    output = {
        'status_code': response.status_code,
        'updated': response.status_code == 200
    }
    

    Request with Custom Headers and Authentication

    import requests
    
    proxy_url = input_data.get('proxy_url')
    api_key = input_data.get('api_key')
    
    proxies = {'http': proxy_url, 'https': proxy_url}
    
    headers = {
        'Authorization': f'Bearer {api_key}',
        'Content-Type': 'application/json',
        'X-Custom-Header': 'Zapier-Integration'
    }
    
    response = requests.get(
        'https://api.example.com/protected-endpoint',
        headers=headers,
        proxies=proxies,
        timeout=25
    )
    
    output = {
        'status_code': response.status_code,
        'data': response.json()
    }
    

    Error Handling

    import requests
    
    proxy_url = input_data.get('proxy_url')
    proxies = {'http': proxy_url, 'https': proxy_url}
    
    try:
        response = requests.get(
            input_data.get('target_url'),
            proxies=proxies,
            timeout=25
        )
        response.raise_for_status()
        
        output = {
            'success': True,
            'status_code': response.status_code,
            'data': response.json() if 'application/json' in response.headers.get('content-type', '') else response.text
        }
        
    except requests.exceptions.Timeout:
        output = {
            'success': False,
            'error': 'Request timed out',
            'error_type': 'timeout'
        }
        
    except requests.exceptions.HTTPError as e:
        output = {
            'success': False,
            'error': str(e),
            'error_type': 'http_error',
            'status_code': e.response.status_code if e.response else None
        }
        
    except requests.exceptions.RequestException as e:
        output = {
            'success': False,
            'error': str(e),
            'error_type': 'request_error'
        }
    

    JavaScript Code Examples

    JavaScript proxy support in Zapier is more complex because the built-in fetch does not support proxy configuration, and you cannot install npm modules like https-proxy-agent.

    To use proxies in JavaScript, you must use the native http and https modules with the HTTP CONNECT method.

    Note: If possible, use Python instead. The Python approach is simpler and more reliable.

    Basic HTTP GET with Proxy (Native http/https)

    const http = require('http');
    const https = require('https');
    const { URL } = require('url');
    
    // Parse proxy URL from Input Data
    const proxyUrl = new URL(inputData.proxy_url);
    const targetUrl = new URL(inputData.target_url || 'https://ip.quotaguard.com');
    
    // Create proxy authorization header
    const proxyAuth = 'Basic ' + Buffer.from(
        proxyUrl.username + ':' + proxyUrl.password
    ).toString('base64');
    
    // Use HTTP CONNECT method to tunnel through proxy
    const tunnelReq = http.request({
        host: proxyUrl.hostname,
        port: proxyUrl.port || 9293,
        method: 'CONNECT',
        path: `${targetUrl.hostname}:443`,
        headers: {
            'Proxy-Authorization': proxyAuth
        }
    });
    
    return new Promise((resolve, reject) => {
        tunnelReq.on('connect', (res, socket) => {
            if (res.statusCode !== 200) {
                reject(new Error(`Proxy connection failed: ${res.statusCode}`));
                return;
            }
            
            // Create HTTPS agent using the tunneled socket
            const agent = new https.Agent({ socket });
            
            const req = https.get({
                hostname: targetUrl.hostname,
                path: targetUrl.pathname + targetUrl.search,
                agent: agent,
                headers: {
                    'Host': targetUrl.hostname
                }
            }, (response) => {
                let data = '';
                response.on('data', chunk => data += chunk);
                response.on('end', () => {
                    try {
                        resolve({
                            status_code: response.statusCode,
                            data: JSON.parse(data)
                        });
                    } catch {
                        resolve({
                            status_code: response.statusCode,
                            data: data
                        });
                    }
                });
            });
            
            req.on('error', reject);
        });
        
        tunnelReq.on('error', reject);
        tunnelReq.end();
    });
    

    Simplified JavaScript Helper Function

    const http = require('http');
    const https = require('https');
    const { URL } = require('url');
    
    async function fetchThroughProxy(targetUrl, proxyUrl, options = {}) {
        const proxy = new URL(proxyUrl);
        const target = new URL(targetUrl);
        
        const proxyAuth = 'Basic ' + Buffer.from(
            proxy.username + ':' + proxy.password
        ).toString('base64');
        
        return new Promise((resolve, reject) => {
            const tunnelReq = http.request({
                host: proxy.hostname,
                port: proxy.port || 9293,
                method: 'CONNECT',
                path: `${target.hostname}:443`,
                headers: { 'Proxy-Authorization': proxyAuth }
            });
            
            tunnelReq.on('connect', (res, socket) => {
                if (res.statusCode !== 200) {
                    reject(new Error(`Proxy failed: ${res.statusCode}`));
                    return;
                }
                
                const agent = new https.Agent({ socket });
                const method = (options.method || 'GET').toUpperCase();
                
                const reqOptions = {
                    hostname: target.hostname,
                    path: target.pathname + target.search,
                    method: method,
                    agent: agent,
                    headers: {
                        'Host': target.hostname,
                        ...options.headers
                    }
                };
                
                const req = https.request(reqOptions, (response) => {
                    let data = '';
                    response.on('data', chunk => data += chunk);
                    response.on('end', () => {
                        resolve({
                            status: response.statusCode,
                            headers: response.headers,
                            body: data
                        });
                    });
                });
                
                req.on('error', reject);
                
                if (options.body) {
                    req.write(options.body);
                }
                req.end();
            });
            
            tunnelReq.on('error', reject);
            tunnelReq.end();
        });
    }
    
    // Usage
    const result = await fetchThroughProxy(
        inputData.target_url,
        inputData.proxy_url
    );
    
    output = {
        status_code: result.status,
        data: result.body
    };
    

    Inbound Webhooks (Reverse Proxy)

    If a secure partner needs to send data TO your Zap but requires a static destination IP to open their firewall, QuotaGuard can help with inbound traffic too.

    How Inbound Proxy Works

    1. Open your QuotaGuard dashboard
    2. Navigate to Setup > Inbound
    3. Enter your Zapier Webhook URL (e.g., https://hooks.zapier.com/hooks/catch/12345/abcdef)
    4. QuotaGuard generates a unique URL like a62b1d0b4983db763450411fd393b3ce-us-east-1.getstatica.com

    Your partner sends requests to this QuotaGuard URL, which resolves to your static IPs. QuotaGuard then forwards the traffic to your actual Zapier webhook.

    Use Case

    A financial institution needs to send transaction data to your Zap but only allows outbound traffic to whitelisted IP addresses. They can whitelist your QuotaGuard static IPs, send data to your QuotaGuard inbound URL, and you receive it in your standard Webhooks by Zapier trigger.

    Database Connections (SOCKS5)

    For non-HTTP protocols like PostgreSQL, MySQL, or MongoDB, use QuotaGuard’s SOCKS5 proxy on port 1080.

    Limitations in Zapier

    Zapier Code steps are ephemeral (serverless). Each execution starts fresh with no persistent connections. This creates challenges for database connections:

    1. Connection must open, execute, and close within Zapier’s timeout limits
    2. Connection pooling is not possible
    3. No keep-alive connections between Zap runs

    Python Database Example

    Python can use SOCKS5 for database connections, but it requires the PySocks library which is not available in Zapier’s environment.

    For database access from Zapier, consider these alternatives:

    1. API Wrapper: Create a simple API endpoint (using AWS Lambda, Google Cloud Functions, or a small server) that accepts HTTP requests and queries your database. Route the HTTP request through QuotaGuard.

    2. Self-hosted automation: For complex database workflows, consider a self-hosted automation platform like n8n where you have full control over the environment.

    3. Database HTTP APIs: Some databases offer HTTP/REST APIs (MongoDB Atlas Data API, Supabase, etc.) that can be accessed through the HTTP proxy.

    Example: Using a Database via HTTP API

    If your database provider offers an HTTP API:

    import requests
    import json
    
    proxy_url = input_data.get('proxy_url')
    db_api_key = input_data.get('db_api_key')
    
    proxies = {'http': proxy_url, 'https': proxy_url}
    
    # Example: MongoDB Atlas Data API
    query = {
        'dataSource': 'Cluster0',
        'database': 'mydb',
        'collection': 'users',
        'filter': {'status': 'active'}
    }
    
    response = requests.post(
        'https://data.mongodb-api.com/app/data-xxxxx/endpoint/data/v1/action/find',
        json=query,
        headers={
            'api-key': db_api_key,
            'Content-Type': 'application/json'
        },
        proxies=proxies,
        timeout=25
    )
    
    output = {
        'documents': response.json().get('documents', [])
    }
    

    Testing Your Implementation

    Create a simple test Zap to verify your proxy configuration:

    Test Zap Structure

    1. Trigger: Manual trigger (or any trigger you want)
    2. Action: Code by Zapier (Run Python)

    Test Code

    import requests
    
    proxy_url = input_data.get('proxy_url')
    proxies = {'http': proxy_url, 'https': proxy_url}
    
    response = requests.get(
        'https://ip.quotaguard.com',
        proxies=proxies,
        timeout=25
    )
    
    result = response.json()
    
    output = {
        'your_static_ip': result.get('ip'),
        'proxy_working': True
    }
    

    Expected Response

    {
        "your_static_ip": "52.34.188.175",
        "proxy_working": true
    }
    

    The returned IP should match one of your two static IPs shown in the QuotaGuard dashboard. Run the Zap multiple times to see both IPs in action (load-balanced).

    Keeping Credentials Secure

    Do not hard-code your QuotaGuard credentials in the Code field. Use Zapier’s Input Data feature instead.

    1. In your Code step, add Input Data fields:
      • Key: proxy_urlValue: Your full QuotaGuard URL
      • Key: api_keyValue: Any API keys for your target service
    2. Reference these in your code:
      proxy_url = input_data.get('proxy_url')
      api_key = input_data.get('api_key')
      

    This keeps credentials:

    • Visible only to Zap editors
    • Out of the code logic
    • Easier to update without modifying code

    Latency Considerations

    Using QuotaGuard adds a network hop to your requests:

    ConfigurationAdded Latency
    Zapier (us-east-1) + QuotaGuard US-East10-30ms
    Cross-region50-100ms

    Zapier Code steps have strict timeout limits. QuotaGuard’s latency is well within these limits and is typically not the bottleneck. The cold-start time of Code steps usually adds more latency than the proxy connection.

    For production Zaps, always include a timeout in your requests (we recommend 25 seconds to leave buffer for Zapier’s limits).

    Troubleshooting

    407 Proxy Authentication Required

    Your proxy credentials are incorrect. Verify:

    1. Username and password in the proxy URL
    2. The URL format is correct: http://username:password@hostname:9293
    3. You’re using the correct QuotaGuard product (Static vs Shield)

    Connection Timeout

    1. Ensure the target URL is correct and accessible
    2. Add explicit timeout to your requests: timeout=25
    3. Check if the target service has additional firewall rules
    4. Verify QuotaGuard proxy hostname is correct

    403 Forbidden (Still Getting Blocked)

    After configuring the proxy, if you still see 403 errors:

    1. Verify the proxy is working by testing with ip.quotaguard.com
    2. Confirm both QuotaGuard IPs are added to the target service’s allowlist
    3. Check if the target service requires additional headers or authentication
    4. Some services block by user-agent. Try adding a custom user-agent header.

    Code Step Errors

    “Process exited before completing request”

    Your code is not returning properly. For Python, ensure you’re setting output. For JavaScript with async code, ensure you’re using await or properly handling Promises.

    “Scripting payload too large”

    The response data exceeds Zapier’s limits. Filter or limit the response data before returning.

    Python Import Errors

    If you see ModuleNotFoundError, you’re trying to import a library not available in Zapier. Only standard library, requests, and BeautifulSoup are available.

    JavaScript Proxy Not Working

    If using JavaScript and the proxy isn’t working:

    1. The built-in fetch does not support proxies. You must use the http/https modules with CONNECT method.
    2. Consider switching to Python which has simpler proxy support.

    QuotaGuard Static vs QuotaGuard Shield

    QuotaGuard offers two products for static IPs:

    FeatureQuotaGuard StaticQuotaGuard Shield
    ProtocolHTTP/SOCKS5HTTPS/SOCKS5 over TLS
    EncryptionStandard proxySSL Passthrough (E2EE)
    Best forGeneral API accessHIPAA, PCI-DSS, regulated data
    Starting price$19/month$69/month

    For most Zapier workflows, QuotaGuard Static provides everything you need. Choose Shield if you’re handling protected health information (PHI), payment card data, or have specific compliance requirements.


    Ready to Get Started?

    Get in touch or create a free trial account.

    Get QuotaGuard for Zapier

    View Zapier Integration Features

    Contact Engineering Support


    Ready to Get Started?

    Get in touch or create a free trial account