guides · drissionpage

DrissionPage and Cloudflare Turnstile

DrissionPage is a well-built Chinese automation library with a design idea the Western ecosystem mostly lacks: one object model that switches between driving a browser and sending plain HTTP, so you use a browser only for the parts that need one. It also handles shadow roots that are not in open state, which is where a Turnstile checkbox lives. Two things to establish before you build on it: its licence forbids commercial use, and its documentation is Chinese-only.

The licence, first, because it is disqualifying for some readers

The README and the package's own __init__.py docstring both carry terms that GitHub cannot classify — which is why the repository shows NOASSERTION rather than a licence name. Translated, they permit personal use "for study and lawful non-profit purposes only", and state that individuals or organisations may not use the project in source or binary form for commercial activity without the copyright holder's authorisation.

That is not an OSI-style open-source licence, and it is a meaningfully different position from the MIT and Apache terms that Patchright, chromedp and most of this ecosystem use. If DrissionPage is going into anything commercial, that is a conversation to have before it becomes load-bearing, not after.

The same terms also forbid use that violates local law or is aimed at attack or harassment, and require respecting robots.txt. Worth reading in full rather than taking this summary's word for it.

What it is, and the idea worth stealing

The name is the design. SessionPage sends HTTP requests. ChromiumPage drives a browser. WebPage is both, with the same element-finding API over either — so a crawl can do the cheap parts as requests and switch to a browser only where rendering is genuinely required, without rewriting the extraction code.

Its README lists advantages over Selenium that are mostly accurate and mostly about ergonomics: no webdriver, so no driver binary to match to a browser version; finding elements across iframes without switching in and out; operating multiple tabs without switching; and — the one that matters here — handling shadow-root elements that are not in open state.

That last capability puts it in the same small group as Patchright: tools that can reach inside a closed shadow root, which is a precondition for touching a Turnstile widget at all rather than a defeat of it.

python
from DrissionPage import ChromiumPage

page = ChromiumPage()
page.get("https://app.example.com/login")

# NOTE: index starts at 1, not 0 — this catches everyone once
el = page.ele("css:input[name=username]", index=1)
el.input("someone@example.com")

ele(locator, index=1) — the index is one-based. Every other library in this space is zero-based, and the resulting off-by-one is quiet rather than loud.

It has no Turnstile handling

This is worth stating flatly, because the shadow-root capability leads people to expect otherwise. The published package contains zero occurrences of turnstile or captcha in any code. The only matches for cloudflare anywhere in it are domain entries inside a public-suffix data file — incidental, not functional.

So what DrissionPage gives you is reach, not a solution. You can locate an element inside the widget's structure; whether an interaction with it is accepted is decided by everything else, and Cloudflare's position on automated browsers solving production challenges is that they are not supported.

Setting a value is input(...), and by_js=True is the documented way to do it through JavaScript rather than simulated keystrokes — the equivalent of execute_script elsewhere. The docstring notes by_js cannot send key combinations, which is the trade-off:

python
import json, os, urllib.request
from DrissionPage import ChromiumPage

SITEKEY = "0x4AAAAAAA_target"
PAGE = "https://app.example.com/login"

req = urllib.request.Request(
    "https://api.solvegate.io/v1/solve",
    data=json.dumps({"gate": "turnstile", "sitekey": SITEKEY, "url": PAGE}).encode(),
    headers={
        "Authorization": f"Bearer {os.environ['SOLVEGATE_KEY']}",
        "Content-Type": "application/json",
    },
)
with urllib.request.urlopen(req, timeout=30) as res:
    token = json.load(res)["token"]

page = ChromiumPage()
page.get(PAGE)
page.run_js(
    """
    const el = document.querySelector('[name="cf-turnstile-response"]');
    el.value = arguments[0];
    el.dispatchEvent(new Event('input', { bubbles: true }));
    """,
    token,
)

The documentation situation

There is no official English documentation. The canonical site is Chinese-only — the /en/ path returns 404 — and the README is entirely in Chinese. The most complete third-party mirror found is also Chinese.

This is not a criticism; it is a planning fact. If nobody on the team reads Chinese, every API question becomes a machine-translation round trip, and the subtleties that matter — like the one-based index above — are exactly the kind that survive translation badly. Budget for it, or pick a tool documented in a language your team reads.

The library itself is substantial: over twelve thousand stars, actively pushed, Python 3.6+, and supporting Chromium-based browsers plus Electron applications.

Where it fits

If you needDrissionPage is
Mixed HTTP and browser work in one APIGenuinely good — this is its distinctive idea
Access inside closed shadow rootsCapable — one of few that state this
Commercial deploymentBlocked by its licence terms without authorisation
English documentationNot available
Any Turnstile-specific handlingNot present — no such code in the package

If the target is your own property and the widget is only in the way of a test, Cloudflare's dummy sitekeys remove the challenge from the test entirely, which is both simpler and their own recommendation.

If it has to clear, a token typically returns in under 1.5 seconds and the request is the same whatever drives the browser. Prepaid credits run from $0.40 per 1,000 down to $0.075 at volume; failed solves are never billed; the first 1,000 are free. The solve reference has the call.

Common questions

Not without the copyright holder's authorisation. Its terms permit personal use for study and lawful non-profit purposes and state that individuals or organisations may not use it in source or binary form for commercial activity. GitHub reports the licence as NOASSERTION because it is not a standard open-source licence.

No. The published package contains no turnstile or captcha code at all — the only cloudflare matches are domain entries in a public-suffix data file. What it offers is the ability to reach elements inside non-open shadow roots, which is a reachability capability rather than a solution.

No official English documentation exists. The canonical documentation site is Chinese-only and its /en/ path returns 404, and the README is entirely in Chinese. Plan for machine translation, or choose a library documented in a language your team reads.

SessionPage sends plain HTTP requests, ChromiumPage drives a browser, and WebPage is both behind one element-finding API. That is the library's distinctive idea: do the cheap parts as requests and switch to a browser only where rendering is genuinely needed, without rewriting the extraction code.

Its index parameter is one-based, not zero-based — index=1 is the first match. Every comparable library is zero-based, so the off-by-one is easy to introduce and it fails quietly by selecting the wrong element rather than raising.

Related

Sources

More in Guides

Playwright and Cloudflare TurnstileStop Cloudflare Turnstile breaking Playwright tests: use Cloudflare's official test sitekeys on staging, or solve a real widget and inject the token.Python Cloudflare Turnstile SolverSolve Cloudflare Turnstile from Python with plain requests or the solvegate SDK. Complete runnable code, async usage, retries, and error handling.Node.js Turnstile solverSolve Cloudflare Turnstile from Node.js: a zero-dependency global fetch version, the solvegate npm SDK, async/await error handling and TypeScript types.How to find a Turnstile sitekey on a pageFind a Cloudflare Turnstile sitekey in seconds: the data-sitekey attribute, keys starting 0x4, explicit-render calls, and Playwright/Node code that extracts it.How to get the cf-turnstile-response tokenWhat the cf-turnstile-response token is, the hidden input it lives in, how siteverify validates it, and how to get one in your own automated tests.Puppeteer Turnstile bypassHow to handle Cloudflare Turnstile in Puppeteer: Cloudflare's official test sitekeys for pages you own, plus a runnable token-injection script.Selenium and Cloudflare Turnstile in PythonHandle Cloudflare Turnstile in Selenium 4 and Python: test sitekeys, explicit waits, execute_script token injection, and what changes in headless.Turnstile fails on a datacenter IPThe same code passes on your laptop and loops forever on a server. What Cloudflare documents about IP reputation, what it does not, and what actually changes.curl_cffi and Turnstilecurl_cffi impersonates TLS and HTTP/2 fingerprints and has no JavaScript runtime. Its own FAQ says so. What that solves, what it cannot, and where the line is.Scrapy and TurnstileScrapy has no JavaScript engine, so a Turnstile page returns markup and no data. The three documented routes, and which one Scrapy's own docs recommend first.undetected-chromedriver and TurnstileIt binary-patches one string out of chromedriver. Its own README says it does not hide your IP and that headless is unfinished. What that means for Turnstile.SeleniumBase and TurnstileThe uc_gui captcha methods use PyAutoGUI and raise in headless mode — the check is in the source. solve_captcha uses CDP and does not. Which to use where.Camoufox and TurnstileCamoufox is a Firefox fork that patches fingerprints at the C++ level. It ships no Turnstile solver, and the issue asking for one was closed as not planned.nodriver and Turnstilenodriver's README documents a tab.cf_verify() that clicks the Cloudflare checkbox. It is not in the shipped code. What the library does do instead.Patchright and TurnstilePatchright is a drop-in Playwright that closes the Runtime.enable leak and reaches into closed shadow roots — which is exactly where a Turnstile checkbox lives.Go, Colly and TurnstileColly has no JavaScript engine — its dependency graph proves it. What that means for Turnstile in Go, and how chromedp and rod compare when you need a browser.

Automating a gate you own or are authorised to test?

// SolveGate clears Cloudflare Turnstile and WAF challenges through one REST call · first 1,000 solves free