Metadata-Version: 2.4
Name: peakfo
Version: 1.1.0
Summary: Python client for the Peak CAPTCHA-solving API: Cloudflare Turnstile and the 5-second challenge
Author-email: "Peak.fo" <support@peak.fo>
License: MIT
Project-URL: Homepage, https://peak.fo/?utm_source=pypi&utm_medium=package&utm_campaign=sdk&utm_content=peakfo-python
Project-URL: Documentation, https://peak.fo/docs?utm_source=pypi&utm_medium=package&utm_campaign=sdk&utm_content=peakfo-python
Project-URL: Repository, https://github.com/CircuitSavage/peakfo-python
Keywords: captcha,turnstile,cloudflare,captcha-solver,cloudflare-turnstile,web-scraping,solver
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.7
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.25.0
Dynamic: license-file

# peakfo: Python client for the Peak CAPTCHA-solving API

`peakfo` is the official Python client for [Peak](https://peak.fo/?utm_source=github&utm_medium=readme&utm_campaign=sdk&utm_content=peakfo-python), an API that solves Cloudflare Turnstile and the Cloudflare 5-second challenge. It wraps the `POST /solve` endpoint, so a solve is one method call.

Peak bills only for solves that succeed. New accounts get 1,000 free solves, no card.

```bash
pip install peakfo
```

## Turnstile

`solve_turnstile` returns a token. Submit it as the `cf-turnstile-response` field of the form you are posting.

```python
from peakfo import PeakClient

client = PeakClient("pk_your_api_key")

result = client.solve_turnstile(
    sitekey="0x4AAAAAAAxxxxxxxx",
    url="https://example.com/",
    proxy="http://user:pass@ip:port",
)
print(result["token"])
```

Leave `proxy` out and the solve runs through Peak's own pool instead (the `TurnstileTaskProxyLess` task). That works for sites that accept the token from any IP. If a site ties the token to the IP that solved it, pass your own proxy.

The sitekey is scoped to the target domain, and the API expects the URL to end with a trailing slash. If the widget sets an `action` or `cdata` value, pass the same values:

```python
client.solve_turnstile(sitekey, url, proxy=proxy, action="login", cdata="session-42")
```

Not sure where the sitekey lives? See [How to find a Cloudflare Turnstile sitekey](https://blog.peak.fo/how-to-find-a-cloudflare-turnstile-sitekey/?utm_source=github&utm_medium=readme&utm_campaign=sdk&utm_content=peakfo-python).

## Cloudflare 5-second challenge

```python
result = client.solve_cloudflare_waf(
    url="https://example.com/",
    proxy="http://user:pass@ip:port",  # sticky session proxy
)

cookies = result["cookies"]                      # includes cf_clearance
user_agent = result["headers"]["user-agent"]     # use this exact string from now on
```

Cloudflare checks that one IP carries the whole session, so use a sticky proxy and keep it for every request that uses the clearance. Only Windows Chrome user agents are supported. To finish the challenge, apply the cookies, POST `result["attributes"]` form-encoded to the target URL with the Referer set to `{url}?__cf_chl_tk={result["cf_rt"]}`, then reuse the session. The [API docs](https://peak.fo/docs?utm_source=github&utm_medium=readme&utm_campaign=sdk&utm_content=peakfo-python) walk through the four steps, and the [cf_clearance explainer](https://blog.peak.fo/the-cf_clearance-cookie-explained-and-how-to-reuse-it/?utm_source=github&utm_medium=readme&utm_campaign=sdk&utm_content=peakfo-python) covers reusing the cookie.

## Balance

```python
print(client.get_balance())   # {'type': 'pay_per_solve', 'balance': ...}
```

## Errors

Every failure raises a subclass of `PeakError`.

```python
from peakfo import (
    PeakClient, PeakError, AuthenticationError,
    InsufficientBalanceError, SolveError, TaskDisabledError,
)

try:
    result = client.solve_turnstile(sitekey, url, proxy=proxy)
except AuthenticationError:
    ...  # missing or invalid API key
except InsufficientBalanceError:
    ...  # top up, or the package is used up
except TaskDisabledError:
    ...  # that task type is switched off right now
except SolveError as e:
    ...  # the solve failed; it was not billed, so retrying is free
except PeakError as e:
    ...  # network error or a non-JSON reply
```

`PeakClient(api_key, timeout=120)` sets the request timeout in seconds.

## App IDs

If you build a tool on top of Peak, create an app ID under Dashboard, Developer, and pass it as `app_id` to any solve method. Peak credits you 5% of the cost of every solve that carries it. The field is optional and has no effect on the solve.

```python
client.solve_turnstile(sitekey, url, app_id="app_your_app_id")
```

## Pricing

Turnstile is $0.90 per 1,000 successful solves, dropping to $0.35 per 1,000 on the largest package. The 5-second challenge is $1.00 per 1,000. Current numbers are on [peak.fo](https://peak.fo/?utm_source=github&utm_medium=readme&utm_campaign=sdk&utm_content=peakfo-python).

## AWS WAF

`solve_aws_waf` is still in the client, but the task is switched off on Peak's side, so calling it raises `TaskDisabledError`.

## Related packages

Peak also publishes drop-in wrappers for [Playwright](https://github.com/CircuitSavage/playwright-turnstile), [Puppeteer](https://github.com/CircuitSavage/puppeteer-extra-plugin-turnstile), [Selenium](https://github.com/CircuitSavage/selenium-turnstile), [Scrapy](https://github.com/CircuitSavage/scrapy-turnstile), [curl_cffi](https://github.com/CircuitSavage/turnstile-curl) and [cloudscraper](https://github.com/CircuitSavage/cloudscraper-turnstile).

## Changelog

**1.1.0**
- `solve_turnstile` accepts no proxy and switches to the proxyless task.
- New optional arguments: `app_id`, and `user_agent` and `html` on the 5-second challenge.
- Non-JSON replies and network errors raise `PeakError` instead of a raw exception.
- `timeout` is now a constructor argument.
- Fixed the README: the free trial is 1,000 solves, and the old price table is gone.

**1.0.0** first release.

## Use

Meant for QA, public-data collection and automation you are allowed to run. Follow each target's terms and robots rules.

MIT licensed. Support: support@peak.fo.
