discover · compare · collections · requirements · contribute · feed · watching · stats · help with your tokens
lexiforest/curl_cffi · source
Snapshot 0 · 2026-11-04T12:47:26Z · Python · MIT
Content fingerprint
187cacb68a422c938d2cafc47c038e3f7338e5b77b1f2c98253a6f21da0154acGitHub description at capture
Python binding for curl-impersonate fork via cffi. A http client that can impersonate browser tls/ja3/http2 fingerprints.
README at capture
# curl_cffi
[](https://pepy.tech/projects/curl-cffi)

[](https://badge.fury.io/py/curl-cffi)
[](https://t.me/impersonate_pro)
[](https://discord.gg/kJqMHHgdn2)
[Documentation](https://curl-cffi.readthedocs.io)
Python binding for [curl-impersonate fork](https://github.com/lexiforest/curl-impersonate)
via [cffi](https://cffi.readthedocs.io/en/latest/). For commercial support, visit [impersonate.pro](https://impersonate.pro).
`curl_cffi` is the most popular Python binding for `curl`. Unlike other pure
python http clients like `httpx` or `requests`, `curl_cffi` can impersonate
browsers' TLS/JA3 and HTTP/2 fingerprints. If you are blocked by some
website for no obvious reason, you can give `curl_cffi` a try.
For JavaScript bindings, see [impers](https://github.com/lexiforest/impers), for solving
JavaScript challenges, see [brimp](https://github.com/lexiforest/brimp).
Python 3.10 is the minimum supported version since v0.14.
## Recent highlights
- 🧭 Our new toy, [brimp](https://github.com/lexiforest/brimp), a lightweight browser, works like curl_cffi with JavaScript enabled. Try it out today!
- 🆕 **0.17.0** updates to curl-impersonate 2.3.0 (curl 8.23.0), with Chrome 151/152, Safari 27, and Firefox 153–155 profiles.
## Recall.ai - API for meeting recordings
<a href="https://www.recall.ai/?utm_source=github&utm_medium=sponsorship&utm_campaign=lexiforest-curl_cffi" target="_blank"><img src="https://cdn.prod.website-files.com/620d732b1f1f7b244ac89f0e/66b294e51ee15f18dd2b171e_recall-logo.svg" alt="Recall.ai" height="47" width="149"></a>
If you’re looking for a meeting recording API, consider checking out [Recall.ai](https://www.recall.ai/?utm_source=github&utm_medium=sponsorship&utm_campaign=lexiforest-curl_cffi), an API that records Zoom, Google Meet, Microsoft Teams, in-person meetings, and more.
## Sponsors
Maintenance of this project is made possible by all the <a href="https://github.com/lexiforest/curl_cffi/graphs/contributors">contributors</a> and <a href="https://github.com/sponsors/lexiforest">sponsors</a>. If you'd like to sponsor this project and have your avatar or company logo appear below <a href="https://github.com/sponsors/lexiforest">click here</a>. 💖
------
### Bypass Cloudflare with API
<a href="https://yescaptcha.com/i/stfnIO" target="_blank"><img src="https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/yescaptcha.png" alt="Yes Captcha!" height="47" width="149"></a>
Yescaptcha is a proxy service that bypasses Cloudflare and uses the API interface to
obtain verified cookies (e.g. `cf_clearance`). Click [here](https://yescaptcha.com/i/stfnIO)
to register: <https://yescaptcha.com/i/stfnIO>
------
<a href="https://hypersolutions.co/?utm_source=github&utm_medium=readme&utm_campaign=curl_cffi" target="_blank"><img src="https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/hypersolutions.png" height="47" width="149"></a>
TLS fingerprinting alone isn't enough for modern bot protection. [Hyper Solutions](https://hypersolutions.co?utm_source=github&utm_medium=readme&utm_campaign=curl_cffi) provides the missing piece - API endpoints that generate valid antibot tokens for:
Akamai • DataDome • Kasada • Incapsula
No browser automation. Just simple API calls that return the exact cookies and headers these systems require.
🚀 [Get Your API Key](https://hypersolutions.co?utm_source=github&utm_medium=readme&utm_campaign=curl_cffi) | 📖 [Docs](https://docs.justhyped.dev) | 💬 [Discord](https://discord.gg/akamai)
------
<a href="https://cloro.dev/?utm_source=referral&utm_medium=curl_cffi" target="_blank"><img src="https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/cloro.png" height="55" width="149"></a>
<a href="https://cloro.dev/?utm_source=referral&utm_medium=curl_cffi">cloro</a>: SERP and AI search API for Google, ChatGPT, Perplexity, Gemini, Copilot and Grok
------
## Impersonate Suite
`curl-cffi` is part of the impersonate suite.
- [curl-impersonate](https://github.com/lexiforest/curl-impersonate). A curl distribution that impersonates browsers.
- [curl_cffi](https://github.com/lexiforest/curl_cffi). Python binding to curl-impersonate.
- [brimp](https://docs.brimp.ai). Browser-impersonate, a lightweight browser
- [impers](https://github.com/lexiforest/impers). Node.js binding to curl-impersonate.
- [impersonate.pro](https://impersonate.pro). Commercial support, more fingerprints and cloud offering.
## Features
- Supports JA3/TLS and http2 fingerprints impersonation, including recent browsers and custom fingerprints.
- Much faster than requests/httpx, on par with aiohttp/pycurl, see [benchmarks](https://github.com/lexiforest/curl_cffi/tree/main/benchmark).
- Mimics the requests API, no need to learn another one.
- Pre-compiled, so you don't have to compile on your machine.
- Supports `asyncio` with proxy rotation on each request.
- Supports http 2.0, which requests does not.
- Supports http 3.0, with fingerprints and udp proxy.
- Supports websocket.
- MIT licensed.
||requests|aiohttp|httpx|pycurl|curl_cffi|
|---|---|---|---|---|---|
|http/2|❌|❌|✅|✅|✅|
|http/3|❌|❌|❌|☑️<sup>1</sup>|✅<sup>2</sup>|
|sync|✅|❌|✅|✅|✅|
|async|❌|✅|✅|❌|✅|
|websocket|❌|✅|❌|❌|✅|
|native retry|❌|❌|❌|❌|✅|
|fingerprints|❌|❌|❌|❌|✅|
|speed|🐇|🐇🐇|🐇|🐇🐇|🐇🐇|
Notes:
1. For pycurl, http/3 is usually disabled at compile time by default.
2. http/3 support since v0.11.4, http/3 proxy and fingerprints since v0.15.0.
## Install
pip install curl_cffi --upgrade
This should work on Linux, macOS and Windows out of the box.
On macOS, you can also install via Homebrew:
brew install lexiforest/tap/curl-cffi
To install beta releases:
pip install curl_cffi --upgrade --pre
To install unstable version from GitHub:
git clone https://github.com/lexiforest/curl_cffi/
cd curl_cffi
make preprocess
pip install .
## Usage
`curl_cffi` comes with a low-level `curl` API and a high-level `requests`-like API.
`curl_cffi` also bundles with a CLI called `curl-cffi`.
### CLI
Since v0.15, `curl_cffi` comes with a CLI called `curl-cffi`, you can use it for debugging
a certain url with the `--impersonate` option. It can also serve as a `web_fetch`
replacement for "agents".
```sh
curl-cffi get tls.browserleaks.com/json
# curl-cffi can be hard to type, use an alias if you want
alias imp=curl-cffi
imp get tls.browserleaks.com/json --impersonate chrome
```
For a complete CLI guide, see [docs](https://curl-cffi.readthedocs.io).
### requests-like
```python
import curl_cffi
# Notice the impersonate parameter
r = curl_cffi.get("https://tls.browserleaks.com/json", impersonate="chrome")
print(r.json())
# output: {..., "ja3n_hash": "aa56c057ad164ec4fdcb7a5a283be9fc", ...}
# the js3n fingerprint should be the same as target browser
# To keep using the latest browser version as `curl_cffi` updates,
# simply set impersonate="chrome" without specifying a version.
# Other similar values are: "safari" and "safari_ios"
r = curl_cffi.get("https://tls.browserleaks.com/json", impersonate="chrome")
# Use http/3 with impersonation
r = curl_cffi.get(
"https://fp.impersonate.pro/api/http3",
http_version="v3",
impersonate="chrome"
)
# To pin a specific version, use version numbers together.
r = curl_cffi.get("https://tls.browserleaks.com/json", impersonate="chrome124")
# To impersonate other than browsers, bring your own ja3/akamai strings
# See examples directory for details.
r = curl_cffi.get("https://tls.browserleaks.com/json", ja3=..., akamai=...)
# http/socks proxies are supported
proxies = {"https": "http://localhost:3128"}
r = curl_cffi.get("https://tls.browserleaks.com/json", impersonate="chrome", proxies=proxies)
proxies = {"https": "socks://localhost:3128"}
r = curl_cffi.get("https://tls.browserleaks.com/json", impersonate="chrome", proxies=proxies)
```
### Sessions
```python
s = curl_cffi.Session()
# httpbin is a http test website, this endpoint makes the server set cookies
s.get("https://httpbin.org/cookies/set/foo/bar")
print(s.cookies)
# <Cookies[<Cookie foo=bar for httpbin.org />]>
# retrieve cookies again to verify
r = s.get("https://httpbin.org/cookies")
print(r.json())
# {'cookies': {'foo': 'bar'}}
```
### Supported impersonate browsers
`curl_cffi` supports the same browser versions preset as supported by our [fork](https://github.com/lexiforest/curl-impersonate) of [curl-impersonate](https://github.com/lwthiker/curl-impersonate):
The open source version of `curl_cffi` includes versions when we are adding new capabilities for impersonating.
If you see a version, e.g. `chrome135`, was skipped, it's simply because there's nothing new or we were busy at that time.
You can simply impersonate it with your own headers and the previous browser target.
For a full list of preset fingerprints, see the [curl-impersonate docs](https://curl-impersonate.readthedocs.io/en/latest/fingerprints.html).
We will no longer put duplicated and outdated info here.
If you don't want to look up the headers/etc by yourself, consider buying commercial support from [impersonate.pro](https://impersonate.pro).
We have comprehensive browser tls, http and JavaScript fingerprints database for almost all the browser versions on various platforms.
Since v0.15.1, you can use `curl-cffi update` to retrieve the latest fingerprints, without updating to a new version.
We offer the Safari, Chrome, Firefox updates for free and others as part of the [commercial plan](https://impersonate.pro).
The current number of fingerprints:



To see the current list of fingerprints on your device, use the command line:
```sh
curl-cffi list
```
To update fingerprints from impersonate.pro, use the command line:
```sh
curl-cffi update
```
If you are trying to impersonate a target other than a browser, use `ja3=...`, `akamai=...`, `extra_fp=...`, and `perk=...`
to specify your own customized fingerprints. See the [docs on impersonation](https://curl-cffi.readthedocs.io/en/latest/impersonate/_index.html) for details.
### Asyncio
```python
from curl_cffi import AsyncSession
async with AsyncSession() as s:
r = await s.get("https://example.com")
```
More concurrency:
```python
import asyncio
from curl_cffi import AsyncSession
urls = [
"https://google.com/",
"https://facebook.com/",
"https://twitter.com/",
]
async with AsyncSession() as s:
tasks = []
for url in urls:
task = s.get(url)
tasks.append(task)
results = await asyncio.gather(*tasks)
```
For low-level APIs, Scrapy integration and other advanced topics, see the
[docs](https://curl-cffi.readthedocs.io) for more details.
### WebSockets
`curl_cffi` provides an advanced Python interface to libcurl's WebSocket client.
WebSocket handshakes go through your session, so they use the same browser impersonation (TLS/JA3 fingerprint), proxies, cookies and headers as your HTTP requests.
```python
from curl_cffi import Session
with Session(impersonate="chrome") as s:
with s.ws_connect("wss://ws.postman-echo.com/raw") as ws:
ws.send_str("Hello, World!")
print(ws.recv_str())
# Hello, World!
```
The sync client also supports an event-driven callback style, similar to `websocket-client`:
```python
from curl_cffi import Session
def on_message(ws, message):
print(message)
with Session() as s:
url = "wss://api.gemini.com/v1/marketdata/BTCUSD"
with s.ws_connect(url, on_message=on_message) as ws:
ws.run_forever()
```
The async client sends and receives concurrently, similar to `aiohttp`:
```python
import asyncio
from curl_cffi import AsyncSession
async def main():
async with AsyncSession(impersonate="chrome") as s:
async with s.ws_connect("wss://ws.postman-echo.com/raw") as ws:
# Sends are queued and return immediately
await asyncio.gather(*(ws.send_str(f"Message {i}") for i in range(3)))
for _ in range(3):
print(await ws.recv_str())
asyncio.run(main())
```
#### Features
- **Browser impersonation:** the handshake uses your session's TLS/JA3 fingerprint, proxies, cookies and headers.
- **Complete messages:** fragmented messages are reassembled for you.
- **Timeouts and retries:** every send and receive accepts a `timeout`, and failed reads can be retried with backoff.
- **Compression:** opt in to `permessage-deflate` with `curl_options={CurlOpt.WS_OPTIONS: CurlWsOption.PERMESSAGE_DEFLATE}` on `ws_connect()`.
- **Fast masking:** outgoing frames are masked with SIMD instructions (AVX-512, AVX2, NEON) in a customized libcurl build.
See the [WebSockets guide](https://curl-cffi.readthedocs.io/en/latest/websockets.html) for callbacks, timeouts, configuration and more.
## Ecosystem
- Integrating with Scrapy: [divtiply/scrapy-curl-cffi](https://github.com/divtiply/scrapy-curl-cffi), [jxlil/scrapy-impersonate](https://github.com/jxlil/scrapy-impersonate) and [tieyongjie/scrapy-fingerprint](https://github.com/tieyongjie/scrapy-fingerprint).
- Integrating with [requests](https://github.com/el1s7/curl-adapter), [httpx](https://github.com/vgavro/httpx-curl-cffi) as adapter.
- Integrating with captcha resolvers: [YesCaptcha](https://yescaptcha.com/i/stfnIO).
## Acknowledgement
- Originally forked from [multippt/python_curl_cffi](https://github.com/multippt/python_curl_cffi), which is under the MIT license.
- Headers/Cookies files are copied from [httpx](https://github.com/encode/httpx/blob/master/httpx/_models.py), which is under the BSD license.
- Asyncio support is inspired by Tornado's curl http client.
- The synchronous WebSocket API is inspired by [websocket_client](https://github.com/websocket-client/websocket-client).
- The asynchronous WebSocket API is inspired by [aiohttp](https://github.com/aio-libs/aiohttp).
## Contributing
When submitting an PR, please use a different branch other than `main` and check the
"Allow edits by maintainers" box, so I can update your PR with lint or style fixes. Thanks!
### AI Policy
- Using AI is neither encouraged nor discouraged, use it by your own choice.
- The bottom line here is that every line of code should be **reviewed by human**, and should be [proven to work](https://simonwillison.net/2025/Dec/18/code-proven-to-work/).
- It's not guaranteed that AI will come up with the cleanest solution, you are responsible to guide it to the right way you know.
- Fix any lint errors, make sure your code follows the established convention in this project.
- LLM tends to generate extensive or none comments, revise the comments and make sure they are concise and helpful.
- It's absolutely **not acceptable** to generate the entire PR summary by LLM. To communicate with other human, use words from a human.
- The only acceptable exception is to fix grammar issues if you are not a native English speaker.
- The essence here is to keep [Human in the loop](https://discourse.llvm.org/t/rfc-llvm-ai-tool-policy-human-in-the-loop/89159)
You can even feed the policy above to your "copilot" to let it adjust the style for you. :P