Mobile Proxy for Airtable Automation
Airtable's Scripting and Automation script environments expose a sandboxed fetch(). It does not accept a proxy option — but you can route through a tiny relay endpoint that forwards via mobile proxy. Here's the pattern that actually works inside Airtable's sandbox.
Prerequisites
- →Airtable Pro+ plan (Automations with scripting).
- →A Cloudflare account (free tier is enough) — or any small serverless platform.
- →Mobile proxy credentials and API key from mobileproxies.org.
Step-by-Step Configuration
Deploy a Cloudflare Worker relay
The worker receives a JSON body with url and a shared secret, then forwards through the mobile proxy using fetch with undici.ProxyAgent:
// worker.js (deploy on Cloudflare Workers)
export default {
async fetch(req, env) {
const auth = req.headers.get('x-relay-key');
if (auth !== env.RELAY_KEY) return new Response('forbidden', { status: 403 });
const { url, method = 'GET', headers = {}, body } = await req.json();
const proxy = `http://${env.PROXY_USER}:${env.PROXY_PASS}@${env.PROXY_HOST}:${env.PROXY_PORT}`;
// Cloudflare Workers don't ship undici; use the fetch-through-relay
// sub-pattern: forward to a tiny Node service hosted on Fly/Railway.
// OR use Workers TCP socket API to speak HTTP CONNECT directly:
const r = await connectAndFetch({ url, method, headers, body, proxy });
return new Response(r.body, { status: r.status, headers: r.headers });
},
};
// connectAndFetch implements: TCP connect → CONNECT host:443 HTTP/1.1
// → upgrade to TLS → send request.
// Reference implementation at github.com/mobileproxies/cf-relay (50 lines).Set the worker's environment variables: PROXY_HOST, PROXY_PORT, PROXY_USER, PROXY_PASS, RELAY_KEY.
Test the worker
curl -X POST https://relay.your-domain.workers.dev \
-H "x-relay-key: SHARED_SECRET" \
-H "content-type: application/json" \
-d '{"url":"https://api.ipify.org"}'
# Should print a mobile carrier IP (not Cloudflare's IP).Airtable Automation script
Trigger: "When record matches conditions". Add a Run a script action. Input variables: recordId (from the trigger), targetUrl (from a column).
const { recordId, targetUrl } = input.config();
const RELAY = "https://relay.your-domain.workers.dev";
const KEY = "SHARED_SECRET";
const res = await fetch(RELAY, {
method: "POST",
headers: { "content-type": "application/json", "x-relay-key": KEY },
body: JSON.stringify({ url: targetUrl, method: "GET" }),
});
const body = await res.text();
const table = base.getTable("Targets");
await table.updateRecordAsync(recordId, {
"Status": res.status,
"Response": body.slice(0, 100000), // Airtable cell limit
"FetchedAt": new Date().toISOString(),
});Trigger rotation from Airtable
Add an Automation "On schedule" trigger (e.g. hourly) with a script that hits the switch endpoint directly — this call doesn't need the relay because it goes to our control plane, not a target site.
const API_KEY = "YOUR_API_KEY";
const SLOT = "us-mob-01";
const r = await fetch(
`https://buy.mobileproxies.org/api/v1/proxies/${SLOT}/switch`,
{ method: "POST", headers: { Authorization: `Bearer ${API_KEY}` } },
);
console.log("rotate status:", r.status);Store the egress IP per record (optional)
Modify the worker to return X-Egress-IP as a response header. Then in the Airtable script, write res.headers.get("x-egress-ip") into an "Egress IP" column — invaluable for debugging which records were scraped from which IP.
Verify It Works
Insert a row with targetUrl = https://api.ipify.org. The Response field should populate with a mobile carrier IP. Check the ASN against carriers like AT&T (AS7018), T-Mobile (AS21928), Vodafone (AS12430). Cloudflare IPs (AS13335) mean the relay isn't actually using the proxy.
Why a Relay? Airtable's Sandbox Limitations
- →Airtable's script environment has no
require(), nohttpsmodule, no agent — onlyfetch. - →You cannot install
https-proxy-agentor any npm dependency. - →Outbound connections come from Airtable's AWS range — useless for sites that flag datacenter ASNs.
- →The relay solves all three: Airtable speaks plain fetch, the relay speaks proxy.
Common Errors
"Script execution exceeded 30 seconds"
Airtable Automations cap script duration at 30s. Move heavier orchestration into the relay (queue + return immediately, store result via Airtable REST API later).
"403 forbidden" from the relay
The x-relay-key header is missing or wrong. Airtable scripts strip unrecognized headers — pass the secret explicitly through fetch(..., { headers: {...} }).
Response too large for a cell
Long text cells cap at ~100KB. Slice the response body before writing, or store the full body in an attachment field via the relay returning a presigned S3 URL.
Related Guides
Mobile IPs Inside Every Airtable Script
$5 trial. Pair with our reference relay and Airtable becomes a fully mobile-egress scraping platform.