How to Solve CAPTCHA in Zapier Without Hitting the Timeout

A Zapier captcha step fails for a reason that has nothing to do with CAPTCHAs: a Code step gets 10 or 30 seconds by default, and a solve takes longer than that. Submit and poll in one step and you time out. The shape that works is two steps with a delay between them, and a solver reachable from Zapier’s servers, which means Server mode rather than the loopback address. Both of those are five minute changes once you know they are the problem.
What you need
- A Zapier account on any plan that includes Code by Zapier.
- CapSkip running in Server mode on a machine Zapier can reach, with a static public IP. See connection settings.
- Key validation switched on, and an API key issued for this Zap.
- The sitekey and page URL of the protected form, from whichever trigger step supplies them.
Server mode is not optional here
Every other guide on this blog starts the solver on 127.0.0.1:8080, and on your own machine that is exactly right. Zapier is not on your machine. Your Zap runs on Zapier’s infrastructure, so a request to 127.0.0.1 from a Code step resolves to Zapier’s own container and gets nothing.
CapSkip’s connection settings have a second mode for this. Local binds to 127.0.0.1 and is reachable only from that device. Server binds to your network or public IP, so a hosted platform can call it over the same 2captcha compatible API. A static public IP is recommended, because the address goes into your Zap and you do not want it moving.
This is still your hardware and still unmetered. Server mode changes where the solver listens, not who owns it and not how it bills. What it does change is exposure, so switch on key validation before you open the port, and give the Zap its own key so you can revoke it without disturbing anything else.
The timeout that decides your Zap’s shape
Code by Zapier runs your Python or JavaScript with a runtime ceiling. On Starter that ceiling is 10 seconds. On Pro, Team and Company it is 30. Zapier also offers extended runtimes that raise a Code step to as much as 10 minutes, which you configure on the step itself.
Now compare that against a solve. An image CAPTCHA is usually seconds. A reCAPTCHA v2 is normally answered somewhere between 15 and 45 seconds, and the polling guidance is to wait roughly 15 to 20 seconds before your first check. So a submit-then-poll loop does not fit inside 10 seconds, usually does not fit inside 30, and fits comfortably inside an extended runtime.
That gives you two designs, and the right one depends on whether extended runtimes are turned on:
- Two steps plus a delay. Works on every plan. Submit, wait, poll. The Zap history reads clearly and a slow solve does not kill the run.
- One step with an extended runtime. Fewer moving parts, and the whole solve lives in one place. Needs the longer runtime enabled on that step.
Step 1: submit the CAPTCHA and keep the ID
Add a Code by Zapier action, choose Python, and map the sitekey and page URL into the step’s input fields. Input values always arrive as strings in input_data, which is fine here because everything you are sending is a string anyway.
# Code by Zapier, Python. requests is available; nothing to install.
SOLVER = "http://YOUR_SERVER_IP:8080"
r = requests.post(SOLVER + "/in.php", data={
"key": input_data["api_key"],
"method": "userrecaptcha",
"googlekey": input_data["sitekey"],
"pageurl": input_data["pageurl"],
"json": 1,
})
body = r.json()
if body["status"] != 1:
raise Exception("Submit rejected: " + body["request"])
# Hand the id to the next step.
output = {"captcha_id": body["request"]}Raising an exception is the right move on a rejected submit. Zapier marks the run as errored and shows the message in the Zap history, which beats passing an error string down the chain and discovering it three steps later.
Step 2: delay, then poll for the token
Add a Delay by Zapier step and use Delay For with a short interval. Twenty seconds is a sensible floor for reCAPTCHA v2, because polling earlier than that just returns CAPCHA_NOT_READY and burns your Code step’s budget on requests that were never going to succeed.
Then add a second Code step that polls. Keep the loop small: a handful of attempts with a sleep between them fits inside 30 seconds, and if the answer is not ready by then the Zap errors and you can turn on Autoreplay rather than sitting in a longer loop.
# Code by Zapier, Python. Second step, after Delay For 20 seconds.
import time
SOLVER = "http://YOUR_SERVER_IP:8080"
params = {
"key": input_data["api_key"],
"action": "get",
"id": input_data["captcha_id"],
"json": 1,
}
token = None
# Five tries at 5s stays inside a 30 second step.
for _ in range(5):
body = requests.get(SOLVER + "/res.php", params=params).json()
if body["status"] == 1:
token = body["request"]
break
if body["request"] != "CAPCHA_NOT_READY":
raise Exception(body["request"])
time.sleep(5)
if not token:
raise Exception("Not solved yet. Lengthen the delay ahead of this step.")
output = {"token": token}CAPCHA_NOT_READY is spelled without the T, and that is the API’s spelling rather than a typo in this post. Every other response you get back is a real error and should stop the Zap. The full list is in the CapSkip API documentation.
The one step version
With extended runtimes enabled on the step, both halves collapse into a single action and the Delay disappears. The code is the two blocks above with the poll loop widened, and the only thing to watch is that your loop’s own ceiling stays under the runtime you configured, so the step raises a message you wrote rather than being killed mid request.
One caution against making the window enormous: a solved token has a limited life of its own. A reCAPTCHA token is single use and stops being accepted after roughly two minutes, so a Zap that solves and then sits in a queue for five will submit something the site has already stopped honouring. Token expiration covers the exact numbers. Solve as late in the Zap as you can, and put the step that uses the token immediately after it.
Using Webhooks by Zapier instead
You can do the submit with Webhooks by Zapier and no code at all. Choose Custom Request or POST, point it at /in.php, and send the same fields as form data. The response comes back as {"status": 1, "request": "<id>"} and Zapier parses it into fields you can map forward.
{
"key": "YOUR_API_KEY",
"method": "userrecaptcha",
"googlekey": "YOUR_SITEKEY",
"pageurl": "https://example.com/page-with-recaptcha",
"json": 1
}Where this gets awkward is the poll. A webhook does one request, so you need a Delay and a Filter to decide whether the answer arrived, and a Zap cannot easily loop back to try again. A Code step reads better for that half. Use Webhooks for the submit if you prefer clicking to typing, and Code for the poll either way.
Common errors and what they mean
| What you see | Cause | Fix |
|---|---|---|
| Your code timed out | Submit and poll in one step on a 10 or 30 second ceiling | Split into two steps with a Delay, or enable extended runtimes |
| Connection refused or a hanging request | The step is calling 127.0.0.1, which is Zapier’s own container | Switch the solver to Server mode and use its public IP |
| ERROR_KEY_DOES_NOT_EXIST | Key validation is on and this Zap’s key is not registered | Issue a key for the Zap in the app settings |
| CAPCHA_NOT_READY on every attempt | Polling started too early, or the loop is too short | Lengthen the Delay before the poll step |
| ERROR_GOOGLEKEY | The sitekey field arrived empty from the trigger | Check the mapping in the step’s input fields |
| Token rejected by the target site | It aged out between the solve and its use | Move the solve later, next to the step that submits it |
FAQ
Can I install the CapSkip SDK in a Code step?
No. Code by Zapier runs in a sandbox with a fixed set of libraries and no package installs, so the Python and Node SDKs are out. It does bundle the requests library, and the API is 2captcha compatible with two endpoints, so the code above is everything the SDK would have done. If part of your pipeline runs somewhere you control, the CAPTCHA solving SDK page covers the four official clients.
Zapier is hosted. How does it reach a solver on my machine?
Through Server mode. The solver binds to your network or public IP instead of the loopback address, and Zapier calls it like any other public API. Give it a static public IP so the address in your Zap stays valid, turn on key validation before you expose the port, and issue the Zap its own key.
How long should the Delay step be?
Start at 20 seconds for reCAPTCHA v2 and about 5 for GeeTest. Image CAPTCHAs come back fast enough that a single step with a one second poll usually covers them. Longer is not automatically safer, because the token starts ageing the moment it is issued, so tune the delay down until you see the occasional retry rather than up until you never see one.
Should I use Zapier or a self-hosted tool for this?
Zapier is the right call when the rest of the workflow already lives there. If the CAPTCHA work is the main event, a tool you host yourself avoids the runtime ceiling entirely and can talk to the solver over a private address. The n8n walkthrough covers that shape, and its Wait node has no equivalent limit.
The short version
Run the solver in Server mode so Zapier can reach it, submit in one Code step, delay about 20 seconds, and poll in a second. Turn on extended runtimes if you would rather have one step. Keep the whole thing tight, because the token expires long before your Zap history does. Costs stay flat whichever design you pick: a captcha solver running on a machine you already own does not charge you per solve, so a Zap that fires four hundred times a day costs exactly what one that fires four times does.
