Skip to main content

Cloudflare Turnstile auto-solver & human-like cursor for Patchright

Project description

header

PyPI Python License

Discord QQ GitHub


🇬🇧 English

Install

pip install latcf

Chromium is installed automatically on first use.

Quick Start

import asyncio
from latcf import latch

async def main():
    cf = await latch(headless=False, turnstile=True)
    page = await cf.new_page()
    await page.goto("https://example.com")
    await cf.close()

asyncio.run(main())

turnstile=True — detection, clicking, retrying, all automatic.

API

Function Description
latch() Launch browser with turnstile auto-solve
latch_context() Launch persistent context with turnstile auto-solve
relate(page) Is there a turnstile on this page?
elate(page) Has the turnstile been solved?
translate(page) Is this a "Just a moment..." page?
collate(page) Grab all cloudflare data (cookies, tokens, etc)
plate() Generate a real-looking user agent
plate_context(opts) Patch your options dict with a real UA

Browser Launch

from latcf import latch, latch_context

cf = await latch(headless=False, turnstile=True)
page = await cf.new_page()

cf = await latch(headless=False, channel="chrome", turnstile=True)

ctx = await latch_context("./profile", headless=False, turnstile=True)

cf = await latch(headless=False, turnstile=False)

await cf.close()

Solver Settings

Defaults work for most cases. Tweak if needed:

from latcf import latch, Latitude

opts = Latitude(
    timeout_ms=3000,
    interval_ms=500,
    foreground=True,
    click_delay_ms=35,
    mouse_move_steps=8,
    wait_after_click_ms=100,
    click_cooldown_ms=5000,
    max_click_cooldown_ms=45000,
    logger=print,
)

cf = await latch(headless=False, turnstile=opts)

The solver watches navigations, DOM changes, page reloads. Before clicking it wanders nearby, pauses like a human, approaches from a random angle. Managed challenge pages are detected and skipped.

Human-Like Cursor

Lateral moves along bezier curves with hand tremor, wind drift, micro-corrections, and overshoot. Click timing uses gaussian distribution.

from latcf import Lateral, Point

cursor = Lateral(page)

await cursor.move_to(Point(640, 360))
await cursor.click(Point(100, 200))
await cursor.double_click(Point(300, 400))
await cursor.scroll(Point(300, 400), delta_y=600, steps=8)
await cursor.hover(Point(300, 400), duration=800)
Action Options
move speed (1.0), jitter (1.5), wind (0.25), overshoot_threshold (500)
click button ("left"), click_count (1), hesitate (0), hold_ms (~85)
scroll delta_x (0), delta_y (300), steps (6), step_delay (60)
hover duration (500), jitter (1.5)

Cloudflare Checks

from latcf import relate, elate, translate, collate

found = await relate(page)       # turnstile present?
solved = await elate(page)       # already solved?
managed = await translate(page)  # managed challenge page?
data = await collate(page)       # get everything

collate() returns a CFData object: cf_clearance, turnstile_tokens, turnstile_sitekeys, cf_cookies, challenge_managed, challenge_cleared, storage_local, storage_session, etc.

Headless UA Patch

Headless chrome leaks HeadlessChrome in the UA. latcf replaces it automatically.

from latcf import plate
ua = plate(channel="chrome")

Env: LAT_CF_HEADLESS_UA=0 to disable, LAT_CF_HEADLESS_UA=<string> for custom.

Use as API

latcf works as a backend for your own API. FastAPI example:

from fastapi import FastAPI
from latcf import latch, collate

app = FastAPI()

@app.get("/solve")
async def solve(url: str):
    cf = await latch(headless=True, turnstile=True)
    page = await cf.new_page()
    await page.goto(url, wait_until="domcontentloaded", timeout=30000)
    data = await collate(page, timeout_ms=15000)
    await cf.close()
    return {
        "solved": data.turnstile_solved,
        "clearance": data.cf_clearance,
        "tokens": data.turnstile_tokens,
    }

uvicorn main:app --host 0.0.0.0 --port 8000 then GET /solve?url=https://example.com.

Requirements

  • Python >= 3.8
  • patchright >= 1.0.0

🇨🇳 中文

安装

pip install latcf

Chromium 会在首次使用时自动安装。

快速上手

import asyncio
from latcf import latch

async def main():
    cf = await latch(headless=False, turnstile=True)
    page = await cf.new_page()
    await page.goto("https://example.com")
    await cf.close()

asyncio.run(main())

turnstile=True — 检测、点击、重试,全自动。

API

函数 作用
latch() 启动浏览器,自动解决 Turnstile
latch_context() 启动持久化上下文,自动解决 Turnstile
relate(page) 页面上有没有 Turnstile?
elate(page) Turnstile 解决了没?
translate(page) 是不是 "Just a moment..." 页面?
collate(page) 拿到所有 Cloudflare 数据(cookie、token 等)
plate() 生成一个看起来真实的 UA
plate_context(opts) 给你的配置加上真实 UA

启动浏览器

from latcf import latch, latch_context

cf = await latch(headless=False, turnstile=True)
page = await cf.new_page()

cf = await latch(headless=False, channel="chrome", turnstile=True)

ctx = await latch_context("./profile", headless=False, turnstile=True)

cf = await latch(headless=False, turnstile=False)

await cf.close()

解决器配置

默认配置大多数情况够用,想调的话:

from latcf import latch, Latitude

opts = Latitude(
    timeout_ms=3000,
    interval_ms=500,
    foreground=True,
    click_delay_ms=35,
    mouse_move_steps=8,
    wait_after_click_ms=100,
    click_cooldown_ms=5000,
    max_click_cooldown_ms=45000,
    logger=print,
)

cf = await latch(headless=False, turnstile=opts)

解决器自动监听页面导航、DOM 变化、页面重载。点击前会在附近随机游荡、像人一样停顿,然后从随机角度接近。托管挑战页面自动识别并跳过。

仿人类鼠标

Lateral 沿贝塞尔曲线移动,带手抖、风漂移、到达微修正、长距离过冲。点击时间用高斯分布。

from latcf import Lateral, Point

cursor = Lateral(page)

await cursor.move_to(Point(640, 360))
await cursor.click(Point(100, 200))
await cursor.double_click(Point(300, 400))
await cursor.scroll(Point(300, 400), delta_y=600, steps=8)
await cursor.hover(Point(300, 400), duration=800)
操作 参数
移动 speed (1.0)、jitter (1.5)、wind (0.25)、overshoot_threshold (500)
点击 button ("left")、click_count (1)、hesitate (0)、hold_ms (~85)
滚动 delta_x (0)、delta_y (300)、steps (6)、step_delay (60)
悬停 duration (500)、jitter (1.5)

Cloudflare 检查

from latcf import relate, elate, translate, collate

found = await relate(page)       # 有没有 Turnstile?
solved = await elate(page)       # 解决了没?
managed = await translate(page)  # 是托管挑战页面吗?
data = await collate(page)       # 拿全部数据

collate() 返回 CFData 对象:cf_clearanceturnstile_tokensturnstile_sitekeyscf_cookieschallenge_managedchallenge_clearedstorage_localstorage_session 等。

Headless UA 修补

Headless 模式的 UA 带 HeadlessChrome,一秒被识别。latcf 自动替换成真实 Chrome UA。

from latcf import plate
ua = plate(channel="chrome")

环境变量:LAT_CF_HEADLESS_UA=0 禁用,LAT_CF_HEADLESS_UA=<字符串> 用自定义的。

作为 API 使用

latcf 可以直接作为后端 API 使用。FastAPI 示例:

from fastapi import FastAPI
from latcf import latch, collate

app = FastAPI()

@app.get("/solve")
async def solve(url: str):
    cf = await latch(headless=True, turnstile=True)
    page = await cf.new_page()
    await page.goto(url, wait_until="domcontentloaded", timeout=30000)
    data = await collate(page, timeout_ms=15000)
    await cf.close()
    return {
        "solved": data.turnstile_solved,
        "clearance": data.cf_clearance,
        "tokens": data.turnstile_tokens,
    }

uvicorn main:app --host 0.0.0.0 --port 8000 启动,然后 GET /solve?url=https://example.com 调用。

依赖

  • Python >= 3.8
  • patchright >= 1.0.0

footer

Discord QQ GitHub

MIT License / Made by ilat

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

latcf-1.0.3.tar.gz (21.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

latcf-1.0.3-py3-none-any.whl (17.6 kB view details)

Uploaded Python 3

File details

Details for the file latcf-1.0.3.tar.gz.

File metadata

  • Download URL: latcf-1.0.3.tar.gz
  • Upload date:
  • Size: 21.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.8.6

File hashes

Hashes for latcf-1.0.3.tar.gz
Algorithm Hash digest
SHA256 6253551e2ee01989d8cbffde0997ec6a22b8728a011f8516e9128eeb8f85f946
MD5 f07438c35951c99dae92c60128d03371
BLAKE2b-256 8f77203d68798d03704dd7a9aaaca4d49d1bc707de5c60920de126e741feb9d8

See more details on using hashes here.

File details

Details for the file latcf-1.0.3-py3-none-any.whl.

File metadata

  • Download URL: latcf-1.0.3-py3-none-any.whl
  • Upload date:
  • Size: 17.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.8.6

File hashes

Hashes for latcf-1.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 9bbc6955e1d6a5c82e561d8d1f30e6696a3a9466546160b40c3750fbf11fa81f
MD5 98eae19bb952434ea846fc4d1051d3e9
BLAKE2b-256 80c46e37b4162ab3f1718072efd0b5fbddd74ea468b33f878b1299d1ce51ad33

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page