{"id":24969,"date":"2026-08-06T10:17:06","date_gmt":"2026-08-06T10:17:06","guid":{"rendered":"https:\/\/capskip.com\/?p=24969"},"modified":"2026-08-06T10:17:06","modified_gmt":"2026-08-06T10:17:06","slug":"recaptcha-v3-python","status":"publish","type":"post","link":"https:\/\/capskip.com\/zh\/recaptcha-v3-python\/","title":{"rendered":"\u5982\u4f55\u7528 Python \u8bc6\u522b reCAPTCHA v3 \u5e76\u8bbe\u7f6e action"},"content":{"rendered":"<p>reCAPTCHA v3 never shows a challenge. It runs in the background and hands the site a token, which the site then verifies server side. From your code that means there is nothing to click and nothing to look at, so the whole job is producing a token the site will accept. In Python that is the same <code>recaptcha<\/code> method you would use for v2, with a version flag.<\/p>\n<p>The part that trips people up is the action.<\/p>\n<h2 style=\"font-size:1.6rem;line-height:1.35;\">Setup<\/h2>\n<pre data-enlighter-language=\"bash\" class=\"EnlighterJSRAW\"># Python 3.10 or newer.\npip install capskip<\/pre>\n<pre data-enlighter-language=\"python\" class=\"EnlighterJSRAW\">from capskip import CapSkip\n\nsolver = CapSkip(\n    host=&quot;127.0.0.1&quot;,\n    port=8080,\n    recaptchaTimeout=300,   # seconds, shared with Turnstile and GeeTest\n)<\/pre>\n<p>CapSkip runs on your own machine, so the desktop app has to be open before any of this works.<\/p>\n<h2 style=\"font-size:1.6rem;line-height:1.35;\">The basic call<\/h2>\n<pre data-enlighter-language=\"python\" class=\"EnlighterJSRAW\">result = solver.recaptcha(\n    sitekey=&quot;6Lc...YOUR_SITEKEY&quot;,\n    url=&quot;https:\/\/example.com\/checkout&quot;,\n    version=&quot;v3&quot;,\n    action=&quot;submit&quot;,\n)\n\nprint(result[&quot;code&quot;])   # the v3 token<\/pre>\n<p>Two things differ from v2. <code>version=\"v3\"<\/code> is required, and <code>action<\/code> should match whatever the page passes to <code>grecaptcha.execute<\/code>. If you omit it the default is <code>verify<\/code>.<\/p>\n<h2 style=\"font-size:1.6rem;line-height:1.35;\">Why the action matters<\/h2>\n<p>v3 actions are labels the site attaches to each protected interaction, so a login and a checkout can be scored separately. The site&#8217;s own backend usually checks that the action on the returned token matches the action it expected for that endpoint.<\/p>\n<p>Send the wrong one and the token is technically valid but arrives labelled for a different interaction, which many backends reject outright. Read the real value out of the page rather than guessing:<\/p>\n<pre data-enlighter-language=\"python\" class=\"EnlighterJSRAW\">import re\nimport requests\n\nhtml = requests.get(&quot;https:\/\/example.com\/checkout&quot;).text\n\n# Sites usually call execute() with the action as a literal string.\nmatch = re.search(r&quot;execute\\([^,]+,\\s*\\{\\s*action:\\s*['\\&quot;]([^'\\&quot;]+)&quot;, html)\naction = match.group(1) if match else &quot;verify&quot;\n\nresult = solver.recaptcha(\n    sitekey=sitekey, url=page_url, version=&quot;v3&quot;, action=action,\n)<\/pre>\n<p>Common values are <code>login<\/code>, <code>submit<\/code>, <code>homepage<\/code> and <code>checkout<\/code>, but they are arbitrary strings chosen by whoever built the site.<\/p>\n<h2 style=\"font-size:1.6rem;line-height:1.35;\">Enterprise v3<\/h2>\n<p>Enterprise is an orthogonal flag rather than a separate product, so it stacks on top:<\/p>\n<pre data-enlighter-language=\"python\" class=\"EnlighterJSRAW\">result = solver.recaptcha(\n    sitekey=sitekey,\n    url=page_url,\n    version=&quot;v3&quot;,\n    enterprise=1,\n    action=&quot;submit&quot;,\n)<\/pre>\n<p>You can tell Enterprise from standard by the script the page loads. Enterprise pulls <code>enterprise.js<\/code>, standard pulls <code>api.js<\/code>. Guessing wrong causes the solve to fail rather than returning a bad token, so it is cheap to check.<\/p>\n<h2 style=\"font-size:1.6rem;line-height:1.35;\">Submitting the token<\/h2>\n<pre data-enlighter-language=\"python\" class=\"EnlighterJSRAW\">import requests\n\nresponse = requests.post(\n    &quot;https:\/\/example.com\/checkout&quot;,\n    data={\n        &quot;g-recaptcha-response&quot;: result[&quot;code&quot;],\n        &quot;order_id&quot;: &quot;...&quot;,\n    },\n)<\/pre>\n<p>Some v3 integrations use a different field name, or send the token as JSON, because there is no standard form widget to constrain them. Check what the page&#8217;s own JavaScript does before assuming <code>g-recaptcha-response<\/code>.<\/p>\n<h2 style=\"font-size:1.6rem;line-height:1.35;\">Solving in bulk<\/h2>\n<p>Python is the only CapSkip SDK where <code>AsyncCapSkip<\/code> is a real async client rather than an alias, so it genuinely overlaps work:<\/p>\n<pre data-enlighter-language=\"python\" class=\"EnlighterJSRAW\">import asyncio\nfrom capskip import AsyncCapSkip\n\nasync def main():\n    solver = AsyncCapSkip()\n    tokens = await asyncio.gather(*[\n        solver.recaptcha(sitekey=sitekey, url=u, version=&quot;v3&quot;, action=&quot;submit&quot;)\n        for u in urls\n    ])\n    return [t[&quot;code&quot;] for t in tokens]\n\nasyncio.run(main())<\/pre>\n<h2 style=\"font-size:1.6rem;line-height:1.35;\">Errors<\/h2>\n<pre data-enlighter-language=\"python\" class=\"EnlighterJSRAW\">from capskip import (\n    ValidationException, NetworkException, ApiException, TimeoutException,\n)\n\ntry:\n    result = solver.recaptcha(sitekey=sitekey, url=page_url, version=&quot;v3&quot;)\nexcept ValidationException:\n    pass   # missing sitekey or url\nexcept NetworkException:\n    pass   # CapSkip is not running\nexcept ApiException:\n    pass   # rejected sitekey or pageurl\nexcept TimeoutException:\n    pass   # exceeded recaptchaTimeout<\/pre>\n<h2 style=\"font-size:1.6rem;line-height:1.35;\">Frequently asked questions<\/h2>\n<details style=\"border:1px solid #e2e5ee;border-radius:10px;padding:14px 18px;margin:0 0 12px;\">\n<summary style=\"cursor:pointer;\">\n<h3 style=\"font-size:1.15rem;line-height:1.4;display:inline;margin:0;\">What happens if I leave out the action?<\/h3>\n<\/summary>\n<p style=\"margin:12px 0 0;\">It defaults to <code>verify<\/code>. That works on sites that never check the action, and fails on sites that do. Since reading the real value out of the page is a few lines, it is worth doing rather than relying on the default.<\/p>\n<\/details>\n<details style=\"border:1px solid #e2e5ee;border-radius:10px;padding:14px 18px;margin:0 0 12px;\">\n<summary style=\"cursor:pointer;\">\n<h3 style=\"font-size:1.15rem;line-height:1.4;display:inline;margin:0;\">Can I check the score before submitting?<\/h3>\n<\/summary>\n<p style=\"margin:12px 0 0;\">No. The score lives with Google and is only revealed to the site owner when their backend verifies the token. From the client side you get a token and nothing else, so there is no way to inspect or filter on the score before you submit.<\/p>\n<\/details>\n<details style=\"border:1px solid #e2e5ee;border-radius:10px;padding:14px 18px;margin:0 0 12px;\">\n<summary style=\"cursor:pointer;\">\n<h3 style=\"font-size:1.15rem;line-height:1.4;display:inline;margin:0;\">How long is a v3 token valid?<\/h3>\n<\/summary>\n<p style=\"margin:12px 0 0;\">About two minutes, and single use, the same as v2. Solve immediately before the request that needs it rather than building up a pool.<\/p>\n<\/details>\n<h2 style=\"font-size:1.6rem;line-height:1.35;\">Summary<\/h2>\n<p>Pass <code>version=\"v3\"<\/code>, set <code>action<\/code> to whatever the page actually uses, add <code>enterprise=1<\/code> when the page loads <code>enterprise.js<\/code>, and submit the token quickly because it expires in about two minutes.<\/p>\n<p>Other languages are covered on the <a href=\"https:\/\/capskip.com\/recaptcha-v3-solver\/\">reCAPTCHA v3 solver<\/a> page, the Enterprise specifics on the <a href=\"https:\/\/capskip.com\/recaptcha-enterprise-solver\/\">Enterprise solver<\/a> page, and the wider Python surface on the <a href=\"https:\/\/capskip.com\/python-captcha-solver\/\">Python CAPTCHA solver<\/a> page. You can watch a real v3 token being generated on our <a href=\"https:\/\/capskip.com\/captcha-demo\/recaptcha-v3\/\">v3 demo<\/a>, and CapSkip itself is an <a href=\"https:\/\/capskip.com\/\">unlimited captcha solver<\/a> that runs locally.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>reCAPTCHA v3 \u4e0e v2 \u662f\u540c\u4e00\u4e2a Python \u65b9\u6cd5\uff0c\u53ea\u591a\u4e86\u4e00\u4e2a version \u6807\u5fd7\u3002\u8ba9\u4eba\u8e29\u5751\u7684\u662f action\uff0c\u5b83\u5fc5\u987b\u4e0e\u9875\u9762\u4f7f\u7528\u7684\u5185\u5bb9\u4e00\u81f4\u3002<\/p>","protected":false},"author":1,"featured_media":24968,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"rank_math_title":"Solve reCAPTCHA v3 in Python | CapSkip","rank_math_description":"reCAPTCHA v3 needs a version flag and an action that matches the page. Here is the Python call for both standard and Enterprise, and where the token goes.","rank_math_focus_keyword":"solve recaptcha v3 in python","footnotes":""},"categories":[71],"tags":[],"class_list":["post-24969","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-google-recaptcha"],"_links":{"self":[{"href":"https:\/\/capskip.com\/zh\/wp-json\/wp\/v2\/posts\/24969","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/capskip.com\/zh\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/capskip.com\/zh\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/capskip.com\/zh\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/capskip.com\/zh\/wp-json\/wp\/v2\/comments?post=24969"}],"version-history":[{"count":1,"href":"https:\/\/capskip.com\/zh\/wp-json\/wp\/v2\/posts\/24969\/revisions"}],"predecessor-version":[{"id":24990,"href":"https:\/\/capskip.com\/zh\/wp-json\/wp\/v2\/posts\/24969\/revisions\/24990"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/capskip.com\/zh\/wp-json\/wp\/v2\/media\/24968"}],"wp:attachment":[{"href":"https:\/\/capskip.com\/zh\/wp-json\/wp\/v2\/media?parent=24969"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/capskip.com\/zh\/wp-json\/wp\/v2\/categories?post=24969"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/capskip.com\/zh\/wp-json\/wp\/v2\/tags?post=24969"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}