# Table of Contents
- [curl_cffi’s documentation — curl_cffi documentation](#curl-cffi-s-documentation-curl-cffi-documentation)
- [curl_cffi’s documentation — curl_cffi documentation](#curl-cffi-s-documentation-curl-cffi-documentation)
- [curl_cffi’s documentation — curl_cffi documentation](#curl-cffi-s-documentation-curl-cffi-documentation)
- [Welcome to curl_cffi’s documentation! — curl_cffi documentation](#welcome-to-curl-cffi-s-documentation-curl-cffi-documentation)
- [Welcome to curl_cffi’s documentation! — curl_cffi documentation](#welcome-to-curl-cffi-s-documentation-curl-cffi-documentation)
- [Welcome to curl_cffi’s documentation! — curl_cffi documentation](#welcome-to-curl-cffi-s-documentation-curl-cffi-documentation)
- [Welcome to curl_cffi’s documentation! — curl_cffi documentation](#welcome-to-curl-cffi-s-documentation-curl-cffi-documentation)
- [Welcome to curl_cffi’s documentation! — curl_cffi documentation](#welcome-to-curl-cffi-s-documentation-curl-cffi-documentation)
- [Welcome to curl_cffi’s documentation! — curl_cffi documentation](#welcome-to-curl-cffi-s-documentation-curl-cffi-documentation)
- [Welcome to curl_cffi’s documentation! — curl_cffi documentation](#welcome-to-curl-cffi-s-documentation-curl-cffi-documentation)
- [curl_cffi’s documentation — curl_cffi documentation](#curl-cffi-s-documentation-curl-cffi-documentation)
- [curl_cffi’s documentation — curl_cffi documentation](#curl-cffi-s-documentation-curl-cffi-documentation)
- [curl_cffi’s documentation — curl_cffi documentation](#curl-cffi-s-documentation-curl-cffi-documentation)
- [curl_cffi’s documentation — curl_cffi documentation](#curl-cffi-s-documentation-curl-cffi-documentation)
- [curl_cffi](#curl-cffi)
- [curl_cffi](#curl-cffi)
- [curl_cffi](#curl-cffi)
- [Welcome to curl_cffi’s documentation! — curl_cffi documentation](#welcome-to-curl-cffi-s-documentation-curl-cffi-documentation)
- [Welcome to curl_cffi’s documentation! — curl_cffi documentation](#welcome-to-curl-cffi-s-documentation-curl-cffi-documentation)
- [Welcome to curl_cffi’s documentation! — curl_cffi documentation](#welcome-to-curl-cffi-s-documentation-curl-cffi-documentation)
- [Welcome to curl_cffi’s documentation! — curl_cffi documentation](#welcome-to-curl-cffi-s-documentation-curl-cffi-documentation)
- [Welcome to curl_cffi’s documentation! — curl_cffi documentation](#welcome-to-curl-cffi-s-documentation-curl-cffi-documentation)
- [Welcome to curl_cffi’s documentation! — curl_cffi documentation](#welcome-to-curl-cffi-s-documentation-curl-cffi-documentation)
- [Welcome to curl_cffi’s documentation! — curl_cffi documentation](#welcome-to-curl-cffi-s-documentation-curl-cffi-documentation)
- [Asyncio — curl_cffi documentation](#asyncio-curl-cffi-documentation)
- [WebSockets — curl_cffi documentation](#websockets-curl-cffi-documentation)
- [Search — curl_cffi documentation](#search-curl-cffi-documentation)
- [Unknown](#unknown)
- [Index — curl_cffi documentation](#index-curl-cffi-documentation)
- [Quick Start — curl_cffi documentation](#quick-start-curl-cffi-documentation)
- [Impersonate Guide — curl_cffi documentation](#impersonate-guide-curl-cffi-documentation)
- [Supported browser impersonate targets — curl_cffi documentation](#supported-browser-impersonate-targets-curl-cffi-documentation)
- [What is TLS and http/2, http/3 fingerprinting? — curl_cffi documentation](#what-is-tls-and-http-2-http-3-fingerprinting-curl-cffi-documentation)
- [Advanced Topics — curl_cffi documentation](#advanced-topics-curl-cffi-documentation)
- [How to use my own fingerprints? e.g. okhttp — curl_cffi documentation](#how-to-use-my-own-fingerprints-e-g-okhttp-curl-cffi-documentation)
- [Compatibility with requests — curl_cffi documentation](#compatibility-with-requests-curl-cffi-documentation)
- [Community — curl_cffi documentation](#community-curl-cffi-documentation)
- [Cookies — curl_cffi documentation](#cookies-curl-cffi-documentation)
- [FAQ — curl_cffi documentation](#faq-curl-cffi-documentation)
- [TLS PSK(41) Extension — curl_cffi documentation](#tls-psk-41-extension-curl-cffi-documentation)
- [Development and contributing — curl_cffi documentation](#development-and-contributing-curl-cffi-documentation)
- [Unknown](#unknown)
- [Search — curl_cffi documentation](#search-curl-cffi-documentation)
- [Asyncio — curl_cffi documentation](#asyncio-curl-cffi-documentation)
- [WebSockets — curl_cffi documentation](#websockets-curl-cffi-documentation)
- [Change Log — curl_cffi documentation](#change-log-curl-cffi-documentation)
- [Impersonation FAQ — curl_cffi documentation](#impersonation-faq-curl-cffi-documentation)
- [API References — curl_cffi documentation](#api-references-curl-cffi-documentation)
- [Index — curl_cffi documentation](#index-curl-cffi-documentation)
- [Supported browser impersonate targets — curl_cffi documentation](#supported-browser-impersonate-targets-curl-cffi-documentation)
- [What is TLS and http/2, http/3 fingerprinting? — curl_cffi documentation](#what-is-tls-and-http-2-http-3-fingerprinting-curl-cffi-documentation)
- [Impersonate Guide — curl_cffi documentation](#impersonate-guide-curl-cffi-documentation)
- [Quick Start — curl_cffi documentation](#quick-start-curl-cffi-documentation)
- [Compatibility with requests — curl_cffi documentation](#compatibility-with-requests-curl-cffi-documentation)
- [TLS PSK(41) Extension — curl_cffi documentation](#tls-psk-41-extension-curl-cffi-documentation)
- [Impersonation FAQ — curl_cffi documentation](#impersonation-faq-curl-cffi-documentation)
- [Cookies — curl_cffi documentation](#cookies-curl-cffi-documentation)
- [How to use my own fingerprints? e.g. okhttp — curl_cffi documentation](#how-to-use-my-own-fingerprints-e-g-okhttp-curl-cffi-documentation)
- [Advanced Topics — curl_cffi documentation](#advanced-topics-curl-cffi-documentation)
- [Community — curl_cffi documentation](#community-curl-cffi-documentation)
- [FAQ — curl_cffi documentation](#faq-curl-cffi-documentation)
- [Change Log — curl_cffi documentation](#change-log-curl-cffi-documentation)
- [API References — curl_cffi documentation](#api-references-curl-cffi-documentation)
- [Index — curl_cffi documentation](#index-curl-cffi-documentation)
- [Index — curl_cffi documentation](#index-curl-cffi-documentation)
- [WebSockets — curl_cffi documentation](#websockets-curl-cffi-documentation)
- [Index — curl_cffi documentation](#index-curl-cffi-documentation)
- [Unknown](#unknown)
- [Search — curl_cffi documentation](#search-curl-cffi-documentation)
- [Index — curl_cffi documentation](#index-curl-cffi-documentation)
- [Development and contributing — curl_cffi documentation](#development-and-contributing-curl-cffi-documentation)
- [Install — curl_cffi documentation](#install-curl-cffi-documentation)
- [Install — curl_cffi documentation](#install-curl-cffi-documentation)
- [Install — curl_cffi documentation](#install-curl-cffi-documentation)
- [Install — curl_cffi documentation](#install-curl-cffi-documentation)
- [Install — curl_cffi documentation](#install-curl-cffi-documentation)
- [Install — curl_cffi documentation](#install-curl-cffi-documentation)
- [Install — curl_cffi documentation](#install-curl-cffi-documentation)
- [Quick Start — curl_cffi documentation](#quick-start-curl-cffi-documentation)
- [Quick Start — curl_cffi documentation](#quick-start-curl-cffi-documentation)
- [Quick Start — curl_cffi documentation](#quick-start-curl-cffi-documentation)
- [Impersonate guide — curl_cffi documentation](#impersonate-guide-curl-cffi-documentation)
- [Impersonate Guide — curl_cffi documentation](#impersonate-guide-curl-cffi-documentation)
- [Cookies — curl_cffi documentation](#cookies-curl-cffi-documentation)
- [Cookies — curl_cffi documentation](#cookies-curl-cffi-documentation)
- [Impersonate guide — curl_cffi documentation](#impersonate-guide-curl-cffi-documentation)
- [Impersonate guide — curl_cffi documentation](#impersonate-guide-curl-cffi-documentation)
- [Asyncio — curl_cffi documentation](#asyncio-curl-cffi-documentation)
- [Impersonate guide — curl_cffi documentation](#impersonate-guide-curl-cffi-documentation)
- [Impersonate guide — curl_cffi documentation](#impersonate-guide-curl-cffi-documentation)
- [Impersonate guide — curl_cffi documentation](#impersonate-guide-curl-cffi-documentation)
- [Impersonate guide — curl_cffi documentation](#impersonate-guide-curl-cffi-documentation)
- [What is TLS and http/2, http/3 fingerprinting? — curl_cffi documentation](#what-is-tls-and-http-2-http-3-fingerprinting-curl-cffi-documentation)
- [Quick Start — curl_cffi documentation](#quick-start-curl-cffi-documentation)
- [What is TLS and http/2, http/3 fingerprinting? — curl_cffi documentation](#what-is-tls-and-http-2-http-3-fingerprinting-curl-cffi-documentation)
- [Cookies — curl_cffi documentation](#cookies-curl-cffi-documentation)
- [Cookies — curl_cffi documentation](#cookies-curl-cffi-documentation)
- [Impersonate Guide — curl_cffi documentation](#impersonate-guide-curl-cffi-documentation)
- [Cookies — curl_cffi documentation](#cookies-curl-cffi-documentation)
- [Cookies — curl_cffi documentation](#cookies-curl-cffi-documentation)
- [Advanced Usage — curl_cffi documentation](#advanced-usage-curl-cffi-documentation)
- [Advanced Usage — curl_cffi documentation](#advanced-usage-curl-cffi-documentation)
- [Advanced Usage — curl_cffi documentation](#advanced-usage-curl-cffi-documentation)
- [Supported browser impersonate targets — curl_cffi documentation](#supported-browser-impersonate-targets-curl-cffi-documentation)
- [Advanced Topics — curl_cffi documentation](#advanced-topics-curl-cffi-documentation)
- [Advanced Topics — curl_cffi documentation](#advanced-topics-curl-cffi-documentation)
- [Compatibility with requests — curl_cffi documentation](#compatibility-with-requests-curl-cffi-documentation)
- [Impersonate Guide — curl_cffi documentation](#impersonate-guide-curl-cffi-documentation)
- [Impersonate Guide — curl_cffi documentation](#impersonate-guide-curl-cffi-documentation)
- [Cookies — curl_cffi documentation](#cookies-curl-cffi-documentation)
- [Advanced Usage — curl_cffi documentation](#advanced-usage-curl-cffi-documentation)
- [Advanced Usage — curl_cffi documentation](#advanced-usage-curl-cffi-documentation)
- [Advanced Usage — curl_cffi documentation](#advanced-usage-curl-cffi-documentation)
- [Advanced Usage — curl_cffi documentation](#advanced-usage-curl-cffi-documentation)
- [Compatibility with requests — curl_cffi documentation](#compatibility-with-requests-curl-cffi-documentation)
- [Supported browser impersonate targets — curl_cffi documentation](#supported-browser-impersonate-targets-curl-cffi-documentation)
- [Compatibility with requests — curl_cffi documentation](#compatibility-with-requests-curl-cffi-documentation)
- [How to use my own fingerprints? e.g. okhttp — curl_cffi documentation](#how-to-use-my-own-fingerprints-e-g-okhttp-curl-cffi-documentation)
- [Compatibility with requests — curl_cffi documentation](#compatibility-with-requests-curl-cffi-documentation)
- [Compatibility with requests — curl_cffi documentation](#compatibility-with-requests-curl-cffi-documentation)
- [Compatibility with requests — curl_cffi documentation](#compatibility-with-requests-curl-cffi-documentation)
- [Community — curl_cffi documentation](#community-curl-cffi-documentation)
- [Cookies — curl_cffi documentation](#cookies-curl-cffi-documentation)
- [Exceptions — curl_cffi documentation](#exceptions-curl-cffi-documentation)
- [TLS PSK(41) Extension — curl_cffi documentation](#tls-psk-41-extension-curl-cffi-documentation)
- [How to use my own fingerprints? e.g. okhttp — curl_cffi documentation](#how-to-use-my-own-fingerprints-e-g-okhttp-curl-cffi-documentation)
- [Exceptions — curl_cffi documentation](#exceptions-curl-cffi-documentation)
- [Cookies — curl_cffi documentation](#cookies-curl-cffi-documentation)
- [Community — curl_cffi documentation](#community-curl-cffi-documentation)
- [Compatibility with requests — curl_cffi documentation](#compatibility-with-requests-curl-cffi-documentation)
- [TLS PSK(41) Extension — curl_cffi documentation](#tls-psk-41-extension-curl-cffi-documentation)
- [Exceptions — curl_cffi documentation](#exceptions-curl-cffi-documentation)
- [Exceptions — curl_cffi documentation](#exceptions-curl-cffi-documentation)
- [Impersonation FAQ — curl_cffi documentation](#impersonation-faq-curl-cffi-documentation)
- [FAQ — curl_cffi documentation](#faq-curl-cffi-documentation)
- [FAQ — curl_cffi documentation](#faq-curl-cffi-documentation)
- [FAQ — curl_cffi documentation](#faq-curl-cffi-documentation)
- [FAQ — curl_cffi documentation](#faq-curl-cffi-documentation)
- [FAQ — curl_cffi documentation](#faq-curl-cffi-documentation)
- [Compatibility with requests — curl_cffi documentation](#compatibility-with-requests-curl-cffi-documentation)
- [FAQ — curl_cffi documentation](#faq-curl-cffi-documentation)
- [FAQ — curl_cffi documentation](#faq-curl-cffi-documentation)
- [Compatibility with requests — curl_cffi documentation](#compatibility-with-requests-curl-cffi-documentation)
- [Index — curl_cffi documentation](#index-curl-cffi-documentation)
- [API References — curl_cffi documentation](#api-references-curl-cffi-documentation)
- [API References — curl_cffi documentation](#api-references-curl-cffi-documentation)
- [API References — curl_cffi documentation](#api-references-curl-cffi-documentation)
- [API References — curl_cffi documentation](#api-references-curl-cffi-documentation)
- [Search — curl_cffi documentation](#search-curl-cffi-documentation)
- [Compatibility with requests — curl_cffi documentation](#compatibility-with-requests-curl-cffi-documentation)
---
# curl_cffi’s documentation — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/latest/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/latest/quick_start.html "Quick Start")
|
* [Top](https://curl-cffi.readthedocs.io/en/latest/#)
»
* [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/latest/)
curl\_cffi’s documentation[¶](https://curl-cffi.readthedocs.io/en/latest/#curl-cffi-s-documentation "Link to this heading")
============================================================================================================================
Contents:
* [Quick Start](https://curl-cffi.readthedocs.io/en/latest/quick_start.html)
* [Install](https://curl-cffi.readthedocs.io/en/latest/quick_start.html#install)
* [requests-like](https://curl-cffi.readthedocs.io/en/latest/quick_start.html#requests-like)
* [Asyncio](https://curl-cffi.readthedocs.io/en/latest/quick_start.html#asyncio)
* [WebSockets](https://curl-cffi.readthedocs.io/en/latest/quick_start.html#websockets)
* [Impersonate Guide](https://curl-cffi.readthedocs.io/en/latest/impersonate/_index.html)
* [What is TLS and http/2, http/3 fingerprinting?](https://curl-cffi.readthedocs.io/en/latest/impersonate/fingerprint.html)
* [Supported browser impersonate targets](https://curl-cffi.readthedocs.io/en/latest/impersonate/targets.html)
* [Which target version to use?](https://curl-cffi.readthedocs.io/en/latest/impersonate/targets.html#which-target-version-to-use)
* [How to use my own fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/latest/impersonate/customize.html)
* [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/latest/impersonate/psk.html)
* [Impersonation FAQ](https://curl-cffi.readthedocs.io/en/latest/impersonate/faq.html)
* [Advanced Topics](https://curl-cffi.readthedocs.io/en/latest/advanced.html)
* [Proxies](https://curl-cffi.readthedocs.io/en/latest/advanced.html#proxies)
* [Low-level curl API](https://curl-cffi.readthedocs.io/en/latest/advanced.html#low-level-curl-api)
* [Using `CURLOPT_*` in requests API](https://curl-cffi.readthedocs.io/en/latest/advanced.html#using-curlopt-in-requests-api)
* [Selecting http version](https://curl-cffi.readthedocs.io/en/latest/advanced.html#selecting-http-version)
* [Keeping session alive in http/2](https://curl-cffi.readthedocs.io/en/latest/advanced.html#keeping-session-alive-in-http-2)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/latest/vs-requests.html)
* [Transports and Adapters](https://curl-cffi.readthedocs.io/en/latest/vs-requests.html#transports-and-adapters)
* [Cookies](https://curl-cffi.readthedocs.io/en/latest/cookies.html)
* [Save and load cookies](https://curl-cffi.readthedocs.io/en/latest/cookies.html#save-and-load-cookies)
* [Discard cookies when using Session](https://curl-cffi.readthedocs.io/en/latest/cookies.html#discard-cookies-when-using-session)
* [Community](https://curl-cffi.readthedocs.io/en/latest/community.html)
* [Scrapy integrations](https://curl-cffi.readthedocs.io/en/latest/community.html#scrapy-integrations)
* [Using with eventlet/gevent](https://curl-cffi.readthedocs.io/en/latest/community.html#using-with-eventlet-gevent)
* [As a urllib3/requests adapter](https://curl-cffi.readthedocs.io/en/latest/community.html#as-a-urllib3-requests-adapter)
* [As a httpx transport](https://curl-cffi.readthedocs.io/en/latest/community.html#as-a-httpx-transport)
* [API References](https://curl-cffi.readthedocs.io/en/latest/api.html)
* [curl low levl APIs](https://curl-cffi.readthedocs.io/en/latest/api.html#curl-low-levl-apis)
* [requests-like API](https://curl-cffi.readthedocs.io/en/latest/api.html#requests-like-api)
* [Asyncio](https://curl-cffi.readthedocs.io/en/latest/api.html#asyncio)
* [WebSocket](https://curl-cffi.readthedocs.io/en/latest/api.html#websocket)
* [Exceptions and Warnings](https://curl-cffi.readthedocs.io/en/latest/api.html#exceptions-and-warnings)
* [FAQ](https://curl-cffi.readthedocs.io/en/latest/faq.html)
* [What does the pro version offer? Is the open source project still maintained?](https://curl-cffi.readthedocs.io/en/latest/faq.html#what-does-the-pro-version-offer-is-the-open-source-project-still-maintained)
* [Why does the JA3 fingerprints change for Chrome 110+ impersonation?](https://curl-cffi.readthedocs.io/en/latest/faq.html#why-does-the-ja3-fingerprints-change-for-chrome-110-impersonation)
* [Can I bypass Cloudflare with this project? or any other specific site.](https://curl-cffi.readthedocs.io/en/latest/faq.html#can-i-bypass-cloudflare-with-this-project-or-any-other-specific-site)
* [I’m getting certs errors](https://curl-cffi.readthedocs.io/en/latest/faq.html#i-m-getting-certs-errors)
* [ErrCode: 77, Reason: error setting certificate verify locations](https://curl-cffi.readthedocs.io/en/latest/faq.html#errcode-77-reason-error-setting-certificate-verify-locations)
* [How to use with fiddler/charles to intercept content](https://curl-cffi.readthedocs.io/en/latest/faq.html#how-to-use-with-fiddler-charles-to-intercept-content)
* [ErrCode: 92, Reason: ‘HTTP/2 stream 0 was not closed cleanly: PROTOCOL\_ERROR (err 1)’](https://curl-cffi.readthedocs.io/en/latest/faq.html#errcode-92-reason-http-2-stream-0-was-not-closed-cleanly-protocol-error-err-1)
* [Packaging with PyInstaller](https://curl-cffi.readthedocs.io/en/latest/faq.html#packaging-with-pyinstaller)
* [How to change the order of headers?](https://curl-cffi.readthedocs.io/en/latest/faq.html#how-to-change-the-order-of-headers)
* [How to deal with encoding/decoding errors?](https://curl-cffi.readthedocs.io/en/latest/faq.html#how-to-deal-with-encoding-decoding-errors)
* [Change Log](https://curl-cffi.readthedocs.io/en/latest/changelog.html)
* [Development and contributing](https://curl-cffi.readthedocs.io/en/latest/dev.html)
* [Contributing](https://curl-cffi.readthedocs.io/en/latest/dev.html#contributing)
[Discuss on Telegram](https://t.me/+lL9n33eZp480MGM1)
curl\_cffi is a 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/)
.
Unlike other pure Python http clients like `httpx` or `requests`, `curl_cffi` can impersonate browsers’ TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try.
If you are looking for Python http3 clients, curl\_cffi added http3 support since `v0.11`.
Sponsors[¶](https://curl-cffi.readthedocs.io/en/latest/#sponsors "Link to this heading")
-----------------------------------------------------------------------------------------
### Bypass Cloudflare with API[¶](https://curl-cffi.readthedocs.io/en/latest/#bypass-cloudflare-with-api "Link to this heading")
[](https://yescaptcha.com/i/stfnIO)
[Yescaptcha](https://yescaptcha.com/i/stfnIO)
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.
You can also click [here](https://buymeacoffee.com/yifei)
to buy me a coffee.
### Residential Proxies[¶](https://curl-cffi.readthedocs.io/en/latest/#residential-proxies "Link to this heading")
[](https://www.thordata.com/?ls=github&lk=curl_cffi)
[Thordata](https://www.thordata.com/?ls=github&lk=curl_cffi)
: A reliable and cost-effective proxy service provider. One-click collection of public network data, providing enterprises and developers with stable, efficient, and compliant global proxy IP services. Register for a free trial of [residential proxies](https://www.thordata.com/products/residential-proxies/?ls=github&lk=curl_cffi)
and receive 2000 free SERP API calls.
Features[¶](https://curl-cffi.readthedocs.io/en/latest/#features "Link to this heading")
-----------------------------------------------------------------------------------------
* 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 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 & 3.0, which requests does not.
* Supports websocket.
| | | | | | |
| --- | --- | --- | --- | --- | --- |Feature matrix[¶](https://curl-cffi.readthedocs.io/en/latest/#id3 "Link to this table")
| | requests | aiohttp | httpx | pycurl | curl\_cffi |
| --- | --- | --- | --- | --- | --- |
| http2 | ❌ | ❌ | ✅ | ✅ | ✅ |
| http3 | ❌ | ❌ | ❌ | ✅ | ✅ |
| sync | ✅ | ❌ | ✅ | ✅ | ✅ |
| async | ❌ | ✅ | ✅ | ❌ | ✅ |
| websocket | ❌ | ✅ | ❌ | ❌ | ✅ |
| native retry | ❌ | ❌ | ❌ | ❌ | ✅ |
| fingerprints | ❌ | ❌ | ❌ | ❌ | ✅ |
| speed | 🐇 | 🐇🐇 | 🐇 | 🐇🐇 | 🐇🐇 |
Notes:
1. For pycurl, you need a http/3 enabled libcurl, while curl\_cffi packages libcurl-impersonate inside Python wheels.
2. Full http/3 supported was added in v0.12.0.
Install[¶](https://curl-cffi.readthedocs.io/en/latest/#install "Link to this heading")
---------------------------------------------------------------------------------------
pip install curl\_cffi \--upgrade
For more details, see [Quick Start](https://curl-cffi.readthedocs.io/en/latest/quick_start.html)
.
Documentation[¶](https://curl-cffi.readthedocs.io/en/latest/#documentation "Link to this heading")
---------------------------------------------------------------------------------------------------
You can first check out [Quick Start](https://curl-cffi.readthedocs.io/en/latest/quick_start.html)
. Then the impersonate.
For advanced topics, checkout [Cookies](https://curl-cffi.readthedocs.io/en/latest/cookies.html)
, [Asyncio](https://curl-cffi.readthedocs.io/en/latest/asyncio.html)
and [WebSockets](https://curl-cffi.readthedocs.io/en/latest/websockets.html)
.
You can also find common use cases in the [examples](https://github.com/lexiforest/curl_cffi/tree/main/examples)
directory.
Finally, if something is missing from the tutorial, you can always find them in the [API References](https://curl-cffi.readthedocs.io/en/latest/api.html)
.
If you have any questions, be sure to check out the [FAQ](https://curl-cffi.readthedocs.io/en/latest/faq.html)
section before opening an issue.
Indices and tables[¶](https://curl-cffi.readthedocs.io/en/latest/#indices-and-tables "Link to this heading")
=============================================================================================================
* [Index](https://curl-cffi.readthedocs.io/en/latest/genindex.html)
* [Module Index](https://curl-cffi.readthedocs.io/en/latest/py-modindex.html)
* [Search Page](https://curl-cffi.readthedocs.io/en/latest/search.html)
[**Stop getting blocked.** Automatic IP rotation for your apps and scripts. **Signup for a free trial today.**](https://server.ethicalads.io/proxy/click/10211/019d20cc-41fd-7601-914b-9e14a1c5f745/)
[Ads by EthicalAds](https://www.ethicalads.io/advertisers/topics/backend-web/?ref=ea-text)
### [Table of Contents](https://curl-cffi.readthedocs.io/en/latest/#)
* [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/latest/#)
* [Sponsors](https://curl-cffi.readthedocs.io/en/latest/#sponsors)
* [Bypass Cloudflare with API](https://curl-cffi.readthedocs.io/en/latest/#bypass-cloudflare-with-api)
* [Residential Proxies](https://curl-cffi.readthedocs.io/en/latest/#residential-proxies)
* [Features](https://curl-cffi.readthedocs.io/en/latest/#features)
* [Install](https://curl-cffi.readthedocs.io/en/latest/#install)
* [Documentation](https://curl-cffi.readthedocs.io/en/latest/#documentation)
* [Indices and tables](https://curl-cffi.readthedocs.io/en/latest/#indices-and-tables)
#### Next topic
[Quick Start](https://curl-cffi.readthedocs.io/en/latest/quick_start.html "next chapter")
### This Page
* [Show Source](https://curl-cffi.readthedocs.io/en/latest/_sources/index.rst.txt)
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/latest/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/latest/quick_start.html "Quick Start")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/latest/#)
»
* [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/latest/)
---
# curl_cffi’s documentation — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/quick_start.html "Quick Start")
|
* [Top](https://curl-cffi.readthedocs.io/en/stable/#)
»
* [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/stable/)
curl\_cffi’s documentation[¶](https://curl-cffi.readthedocs.io/en/stable/#curl-cffi-s-documentation "Link to this heading")
============================================================================================================================
Contents:
* [Quick Start](https://curl-cffi.readthedocs.io/en/stable/quick_start.html)
* [Install](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#install)
* [requests-like](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#requests-like)
* [Asyncio](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#asyncio)
* [WebSockets](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#websockets)
* [Impersonate Guide](https://curl-cffi.readthedocs.io/en/stable/impersonate/_index.html)
* [What is TLS and http/2, http/3 fingerprinting?](https://curl-cffi.readthedocs.io/en/stable/impersonate/fingerprint.html)
* [Supported browser impersonate targets](https://curl-cffi.readthedocs.io/en/stable/impersonate/targets.html)
* [Which target version to use?](https://curl-cffi.readthedocs.io/en/stable/impersonate/targets.html#which-target-version-to-use)
* [How to use my own fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/stable/impersonate/customize.html)
* [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/stable/impersonate/psk.html)
* [Impersonation FAQ](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html)
* [Advanced Topics](https://curl-cffi.readthedocs.io/en/stable/advanced.html)
* [Proxies](https://curl-cffi.readthedocs.io/en/stable/advanced.html#proxies)
* [Low-level curl API](https://curl-cffi.readthedocs.io/en/stable/advanced.html#low-level-curl-api)
* [Using `CURLOPT_*` in requests API](https://curl-cffi.readthedocs.io/en/stable/advanced.html#using-curlopt-in-requests-api)
* [Selecting http version](https://curl-cffi.readthedocs.io/en/stable/advanced.html#selecting-http-version)
* [Keeping session alive in http/2](https://curl-cffi.readthedocs.io/en/stable/advanced.html#keeping-session-alive-in-http-2)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/stable/vs-requests.html)
* [Transports and Adapters](https://curl-cffi.readthedocs.io/en/stable/vs-requests.html#transports-and-adapters)
* [Cookies](https://curl-cffi.readthedocs.io/en/stable/cookies.html)
* [Save and load cookies](https://curl-cffi.readthedocs.io/en/stable/cookies.html#save-and-load-cookies)
* [Discard cookies when using Session](https://curl-cffi.readthedocs.io/en/stable/cookies.html#discard-cookies-when-using-session)
* [Community](https://curl-cffi.readthedocs.io/en/stable/community.html)
* [Scrapy integrations](https://curl-cffi.readthedocs.io/en/stable/community.html#scrapy-integrations)
* [Using with eventlet/gevent](https://curl-cffi.readthedocs.io/en/stable/community.html#using-with-eventlet-gevent)
* [As a urllib3/requests adapter](https://curl-cffi.readthedocs.io/en/stable/community.html#as-a-urllib3-requests-adapter)
* [As a httpx transport](https://curl-cffi.readthedocs.io/en/stable/community.html#as-a-httpx-transport)
* [API References](https://curl-cffi.readthedocs.io/en/stable/api.html)
* [curl low levl APIs](https://curl-cffi.readthedocs.io/en/stable/api.html#curl-low-levl-apis)
* [requests-like API](https://curl-cffi.readthedocs.io/en/stable/api.html#requests-like-api)
* [Asyncio](https://curl-cffi.readthedocs.io/en/stable/api.html#asyncio)
* [WebSocket](https://curl-cffi.readthedocs.io/en/stable/api.html#websocket)
* [Exceptions and Warnings](https://curl-cffi.readthedocs.io/en/stable/api.html#exceptions-and-warnings)
* [FAQ](https://curl-cffi.readthedocs.io/en/stable/faq.html)
* [What does the pro version offer? Is the open source project still maintained?](https://curl-cffi.readthedocs.io/en/stable/faq.html#what-does-the-pro-version-offer-is-the-open-source-project-still-maintained)
* [Why does the JA3 fingerprints change for Chrome 110+ impersonation?](https://curl-cffi.readthedocs.io/en/stable/faq.html#why-does-the-ja3-fingerprints-change-for-chrome-110-impersonation)
* [Can I bypass Cloudflare with this project? or any other specific site.](https://curl-cffi.readthedocs.io/en/stable/faq.html#can-i-bypass-cloudflare-with-this-project-or-any-other-specific-site)
* [I’m getting certs errors](https://curl-cffi.readthedocs.io/en/stable/faq.html#i-m-getting-certs-errors)
* [ErrCode: 77, Reason: error setting certificate verify locations](https://curl-cffi.readthedocs.io/en/stable/faq.html#errcode-77-reason-error-setting-certificate-verify-locations)
* [How to use with fiddler/charles to intercept content](https://curl-cffi.readthedocs.io/en/stable/faq.html#how-to-use-with-fiddler-charles-to-intercept-content)
* [ErrCode: 92, Reason: ‘HTTP/2 stream 0 was not closed cleanly: PROTOCOL\_ERROR (err 1)’](https://curl-cffi.readthedocs.io/en/stable/faq.html#errcode-92-reason-http-2-stream-0-was-not-closed-cleanly-protocol-error-err-1)
* [Packaging with PyInstaller](https://curl-cffi.readthedocs.io/en/stable/faq.html#packaging-with-pyinstaller)
* [How to change the order of headers?](https://curl-cffi.readthedocs.io/en/stable/faq.html#how-to-change-the-order-of-headers)
* [How to deal with encoding/decoding errors?](https://curl-cffi.readthedocs.io/en/stable/faq.html#how-to-deal-with-encoding-decoding-errors)
* [Change Log](https://curl-cffi.readthedocs.io/en/stable/changelog.html)
* [Development and contributing](https://curl-cffi.readthedocs.io/en/stable/dev.html)
* [Contributing](https://curl-cffi.readthedocs.io/en/stable/dev.html#contributing)
[Discuss on Telegram](https://t.me/+lL9n33eZp480MGM1)
curl\_cffi is a 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/)
.
Unlike other pure Python http clients like `httpx` or `requests`, `curl_cffi` can impersonate browsers’ TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try.
If you are looking for Python http3 clients, curl\_cffi added http3 support since `v0.11`.
Sponsors[¶](https://curl-cffi.readthedocs.io/en/stable/#sponsors "Link to this heading")
-----------------------------------------------------------------------------------------
### Bypass Cloudflare with API[¶](https://curl-cffi.readthedocs.io/en/stable/#bypass-cloudflare-with-api "Link to this heading")
[](https://yescaptcha.com/i/stfnIO)
[Yescaptcha](https://yescaptcha.com/i/stfnIO)
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.
You can also click [here](https://buymeacoffee.com/yifei)
to buy me a coffee.
Features[¶](https://curl-cffi.readthedocs.io/en/stable/#features "Link to this heading")
-----------------------------------------------------------------------------------------
* 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 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 & 3.0, which requests does not.
* Supports websocket.
| | | | | | |
| --- | --- | --- | --- | --- | --- |Feature matrix[¶](https://curl-cffi.readthedocs.io/en/stable/#id2 "Link to this table")
| | requests | aiohttp | httpx | pycurl | curl\_cffi |
| --- | --- | --- | --- | --- | --- |
| http2 | ❌ | ❌ | ✅ | ✅ | ✅ |
| http3 | ❌ | ❌ | ❌ | ✅ | ✅ |
| sync | ✅ | ❌ | ✅ | ✅ | ✅ |
| async | ❌ | ✅ | ✅ | ❌ | ✅ |
| websocket | ❌ | ✅ | ❌ | ❌ | ✅ |
| fingerprints | ❌ | ❌ | ❌ | ❌ | ✅ |
| speed | 🐇 | 🐇🐇 | 🐇 | 🐇🐇 | 🐇🐇 |
Notes:
1. For pycurl, you need a http/3 enabled libcurl, while curl\_cffi packages libcurl-impersonate inside Python wheels.
2. Full http/3 supported was added in v0.12.0.
Install[¶](https://curl-cffi.readthedocs.io/en/stable/#install "Link to this heading")
---------------------------------------------------------------------------------------
pip install curl\_cffi \--upgrade
For more details, see [Quick Start](https://curl-cffi.readthedocs.io/en/stable/quick_start.html)
.
Documentation[¶](https://curl-cffi.readthedocs.io/en/stable/#documentation "Link to this heading")
---------------------------------------------------------------------------------------------------
You can first check out [Quick Start](https://curl-cffi.readthedocs.io/en/stable/quick_start.html)
. Then the impersonate.
For advanced topics, checkout [Cookies](https://curl-cffi.readthedocs.io/en/stable/cookies.html)
, [Asyncio](https://curl-cffi.readthedocs.io/en/stable/asyncio.html)
and [WebSockets](https://curl-cffi.readthedocs.io/en/stable/websockets.html)
.
You can also find common use cases in the [examples](https://github.com/lexiforest/curl_cffi/tree/main/examples)
directory.
Finally, if something is missing from the tutorial, you can always find them in the [API References](https://curl-cffi.readthedocs.io/en/stable/api.html)
.
If you have any questions, be sure to check out the [FAQ](https://curl-cffi.readthedocs.io/en/stable/faq.html)
section before opening an issue.
Indices and tables[¶](https://curl-cffi.readthedocs.io/en/stable/#indices-and-tables "Link to this heading")
=============================================================================================================
* [Index](https://curl-cffi.readthedocs.io/en/stable/genindex.html)
* [Module Index](https://curl-cffi.readthedocs.io/en/stable/py-modindex.html)
* [Search Page](https://curl-cffi.readthedocs.io/en/stable/search.html)
[**Stop getting blocked.** Automatic IP rotation for your apps and scripts. **Signup for a free trial today.**](https://server.ethicalads.io/proxy/click/10211/019d20cc-41fd-7601-914b-9e14a1c5f745/)
[Ads by EthicalAds](https://www.ethicalads.io/advertisers/topics/backend-web/?ref=ea-text)
### [Table of Contents](https://curl-cffi.readthedocs.io/en/stable/#)
* [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/stable/#)
* [Sponsors](https://curl-cffi.readthedocs.io/en/stable/#sponsors)
* [Bypass Cloudflare with API](https://curl-cffi.readthedocs.io/en/stable/#bypass-cloudflare-with-api)
* [Features](https://curl-cffi.readthedocs.io/en/stable/#features)
* [Install](https://curl-cffi.readthedocs.io/en/stable/#install)
* [Documentation](https://curl-cffi.readthedocs.io/en/stable/#documentation)
* [Indices and tables](https://curl-cffi.readthedocs.io/en/stable/#indices-and-tables)
#### Next topic
[Quick Start](https://curl-cffi.readthedocs.io/en/stable/quick_start.html "next chapter")
### This Page
* [Show Source](https://curl-cffi.readthedocs.io/en/stable/_sources/index.rst.txt)
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/quick_start.html "Quick Start")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/#)
»
* [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/stable/)
---
# curl_cffi’s documentation — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html "Quick Start")
|
* [Top](https://curl-cffi.readthedocs.io/en/v0.14.0/#)
»
* [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/)
curl\_cffi’s documentation[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/#curl-cffi-s-documentation "Link to this heading")
=============================================================================================================================
Contents:
* [Quick Start](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html)
* [Install](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#install)
* [requests-like](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#requests-like)
* [Asyncio](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#asyncio)
* [WebSockets](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#websockets)
* [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/_index.html)
* [What is TLS and http/2, http/3 fingerprinting?](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/fingerprint.html)
* [Supported browser impersonate targets](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/targets.html)
* [Which target version to use?](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/targets.html#which-target-version-to-use)
* [How to use my own fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/customize.html)
* [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/psk.html)
* [Impersonation FAQ](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/faq.html)
* [Advanced Topics](https://curl-cffi.readthedocs.io/en/v0.14.0/advanced.html)
* [Proxies](https://curl-cffi.readthedocs.io/en/v0.14.0/advanced.html#proxies)
* [Low-level curl API](https://curl-cffi.readthedocs.io/en/v0.14.0/advanced.html#low-level-curl-api)
* [Using `CURLOPT_*` in requests API](https://curl-cffi.readthedocs.io/en/v0.14.0/advanced.html#using-curlopt-in-requests-api)
* [Selecting http version](https://curl-cffi.readthedocs.io/en/v0.14.0/advanced.html#selecting-http-version)
* [Keeping session alive in http/2](https://curl-cffi.readthedocs.io/en/v0.14.0/advanced.html#keeping-session-alive-in-http-2)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.14.0/vs-requests.html)
* [Transports and Adapters](https://curl-cffi.readthedocs.io/en/v0.14.0/vs-requests.html#transports-and-adapters)
* [Cookies](https://curl-cffi.readthedocs.io/en/v0.14.0/cookies.html)
* [Save and load cookies](https://curl-cffi.readthedocs.io/en/v0.14.0/cookies.html#save-and-load-cookies)
* [Discard cookies when using Session](https://curl-cffi.readthedocs.io/en/v0.14.0/cookies.html#discard-cookies-when-using-session)
* [Community](https://curl-cffi.readthedocs.io/en/v0.14.0/community.html)
* [Scrapy integrations](https://curl-cffi.readthedocs.io/en/v0.14.0/community.html#scrapy-integrations)
* [Using with eventlet/gevent](https://curl-cffi.readthedocs.io/en/v0.14.0/community.html#using-with-eventlet-gevent)
* [As a urllib3/requests adapter](https://curl-cffi.readthedocs.io/en/v0.14.0/community.html#as-a-urllib3-requests-adapter)
* [As a httpx transport](https://curl-cffi.readthedocs.io/en/v0.14.0/community.html#as-a-httpx-transport)
* [API References](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html)
* [curl low levl APIs](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl-low-levl-apis)
* [requests-like API](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#requests-like-api)
* [Asyncio](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#asyncio)
* [WebSocket](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#websocket)
* [Exceptions and Warnings](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#exceptions-and-warnings)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.14.0/faq.html)
* [What does the pro version offer? Is the open source project still maintained?](https://curl-cffi.readthedocs.io/en/v0.14.0/faq.html#what-does-the-pro-version-offer-is-the-open-source-project-still-maintained)
* [Why does the JA3 fingerprints change for Chrome 110+ impersonation?](https://curl-cffi.readthedocs.io/en/v0.14.0/faq.html#why-does-the-ja3-fingerprints-change-for-chrome-110-impersonation)
* [Can I bypass Cloudflare with this project? or any other specific site.](https://curl-cffi.readthedocs.io/en/v0.14.0/faq.html#can-i-bypass-cloudflare-with-this-project-or-any-other-specific-site)
* [I’m getting certs errors](https://curl-cffi.readthedocs.io/en/v0.14.0/faq.html#i-m-getting-certs-errors)
* [ErrCode: 77, Reason: error setting certificate verify locations](https://curl-cffi.readthedocs.io/en/v0.14.0/faq.html#errcode-77-reason-error-setting-certificate-verify-locations)
* [How to use with fiddler/charles to intercept content](https://curl-cffi.readthedocs.io/en/v0.14.0/faq.html#how-to-use-with-fiddler-charles-to-intercept-content)
* [ErrCode: 92, Reason: ‘HTTP/2 stream 0 was not closed cleanly: PROTOCOL\_ERROR (err 1)’](https://curl-cffi.readthedocs.io/en/v0.14.0/faq.html#errcode-92-reason-http-2-stream-0-was-not-closed-cleanly-protocol-error-err-1)
* [Packaging with PyInstaller](https://curl-cffi.readthedocs.io/en/v0.14.0/faq.html#packaging-with-pyinstaller)
* [How to change the order of headers?](https://curl-cffi.readthedocs.io/en/v0.14.0/faq.html#how-to-change-the-order-of-headers)
* [How to deal with encoding/decoding errors?](https://curl-cffi.readthedocs.io/en/v0.14.0/faq.html#how-to-deal-with-encoding-decoding-errors)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.14.0/changelog.html)
* [Development and contributing](https://curl-cffi.readthedocs.io/en/v0.14.0/dev.html)
* [Contributing](https://curl-cffi.readthedocs.io/en/v0.14.0/dev.html#contributing)
[Discuss on Telegram](https://t.me/+lL9n33eZp480MGM1)
curl\_cffi is a 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/)
.
Unlike other pure Python http clients like `httpx` or `requests`, `curl_cffi` can impersonate browsers’ TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try.
If you are looking for Python http3 clients, curl\_cffi added http3 support since `v0.11`.
Sponsors[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/#sponsors "Link to this heading")
------------------------------------------------------------------------------------------
### Bypass Cloudflare with API[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/#bypass-cloudflare-with-api "Link to this heading")
[](https://yescaptcha.com/i/stfnIO)
[Yescaptcha](https://yescaptcha.com/i/stfnIO)
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.
You can also click [here](https://buymeacoffee.com/yifei)
to buy me a coffee.
Features[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/#features "Link to this heading")
------------------------------------------------------------------------------------------
* 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 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 & 3.0, which requests does not.
* Supports websocket.
| | | | | | |
| --- | --- | --- | --- | --- | --- |Feature matrix[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/#id2 "Link to this table")
| | requests | aiohttp | httpx | pycurl | curl\_cffi |
| --- | --- | --- | --- | --- | --- |
| http2 | ❌ | ❌ | ✅ | ✅ | ✅ |
| http3 | ❌ | ❌ | ❌ | ✅ | ✅ |
| sync | ✅ | ❌ | ✅ | ✅ | ✅ |
| async | ❌ | ✅ | ✅ | ❌ | ✅ |
| websocket | ❌ | ✅ | ❌ | ❌ | ✅ |
| fingerprints | ❌ | ❌ | ❌ | ❌ | ✅ |
| speed | 🐇 | 🐇🐇 | 🐇 | 🐇🐇 | 🐇🐇 |
Notes:
1. For pycurl, you need a http/3 enabled libcurl, while curl\_cffi packages libcurl-impersonate inside Python wheels.
2. Full http/3 supported was added in v0.12.0.
Install[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/#install "Link to this heading")
----------------------------------------------------------------------------------------
pip install curl\_cffi \--upgrade
For more details, see [Quick Start](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html)
.
Documentation[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/#documentation "Link to this heading")
----------------------------------------------------------------------------------------------------
You can first check out [Quick Start](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html)
. Then the impersonate.
For advanced topics, checkout [Cookies](https://curl-cffi.readthedocs.io/en/v0.14.0/cookies.html)
, [Asyncio](https://curl-cffi.readthedocs.io/en/v0.14.0/asyncio.html)
and [WebSockets](https://curl-cffi.readthedocs.io/en/v0.14.0/websockets.html)
.
You can also find common use cases in the [examples](https://github.com/lexiforest/curl_cffi/tree/main/examples)
directory.
Finally, if something is missing from the tutorial, you can always find them in the [API References](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html)
.
If you have any questions, be sure to check out the [FAQ](https://curl-cffi.readthedocs.io/en/v0.14.0/faq.html)
section before opening an issue.
Indices and tables[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/#indices-and-tables "Link to this heading")
==============================================================================================================
* [Index](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html)
* [Module Index](https://curl-cffi.readthedocs.io/en/v0.14.0/py-modindex.html)
* [Search Page](https://curl-cffi.readthedocs.io/en/v0.14.0/search.html)
### [Table of Contents](https://curl-cffi.readthedocs.io/en/v0.14.0/#)
* [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/#)
* [Sponsors](https://curl-cffi.readthedocs.io/en/v0.14.0/#sponsors)
* [Bypass Cloudflare with API](https://curl-cffi.readthedocs.io/en/v0.14.0/#bypass-cloudflare-with-api)
* [Features](https://curl-cffi.readthedocs.io/en/v0.14.0/#features)
* [Install](https://curl-cffi.readthedocs.io/en/v0.14.0/#install)
* [Documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/#documentation)
* [Indices and tables](https://curl-cffi.readthedocs.io/en/v0.14.0/#indices-and-tables)
#### Next topic
[Quick Start](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html "next chapter")
### This Page
* [Show Source](https://curl-cffi.readthedocs.io/en/v0.14.0/_sources/index.rst.txt)
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html "Quick Start")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/#)
»
* [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/)
---
# Welcome to curl_cffi’s documentation! — curl_cffi documentation
Welcome to curl\_cffi’s documentation
===================================================================================================================================================
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.7.2/install.html)
* [Via pip](https://curl-cffi.readthedocs.io/en/v0.7.2/install.html#via-pip)
* [Beta versions](https://curl-cffi.readthedocs.io/en/v0.7.2/install.html#beta-versions)
* [Latest](https://curl-cffi.readthedocs.io/en/v0.7.2/install.html#latest)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.7.2/impersonate.html)
* [Supported browser versions](https://curl-cffi.readthedocs.io/en/v0.7.2/impersonate.html#supported-browser-versions)
* [Which version to use?](https://curl-cffi.readthedocs.io/en/v0.7.2/impersonate.html#which-version-to-use)
* [How to use my own fingerprints other than the builtin ones? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.7.2/impersonate.html#how-to-use-my-own-fingerprints-other-than-the-builtin-ones-e-g-okhttp)
* [Should I randomize my fingerprints for each request?](https://curl-cffi.readthedocs.io/en/v0.7.2/impersonate.html#should-i-randomize-my-fingerprints-for-each-request)
* [Can I change JavaScript fingerprints with this library?](https://curl-cffi.readthedocs.io/en/v0.7.2/impersonate.html#can-i-change-javascript-fingerprints-with-this-library)
* [Cookies](https://curl-cffi.readthedocs.io/en/v0.7.2/cookies.html)
* [How to save and load cookies](https://curl-cffi.readthedocs.io/en/v0.7.2/cookies.html#how-to-save-and-load-cookies)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.7.2/advanced.html)
* [low-level curl API](https://curl-cffi.readthedocs.io/en/v0.7.2/advanced.html#low-level-curl-api)
* [scrapy integrations](https://curl-cffi.readthedocs.io/en/v0.7.2/advanced.html#scrapy-integrations)
* [Using with eventlet/gevent](https://curl-cffi.readthedocs.io/en/v0.7.2/advanced.html#using-with-eventlet-gevent)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.7.2/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.7.2/faq.html)
* [Why does the JA3 fingerprints change for Chrome 110+ impersonation?](https://curl-cffi.readthedocs.io/en/v0.7.2/faq.html#why-does-the-ja3-fingerprints-change-for-chrome-110-impersonation)
* [Can I bypass Cloudflare with this project? or any other specific site.](https://curl-cffi.readthedocs.io/en/v0.7.2/faq.html#can-i-bypass-cloudflare-with-this-project-or-any-other-specific-site)
* [I’m getting certs errors](https://curl-cffi.readthedocs.io/en/v0.7.2/faq.html#i-m-getting-certs-errors)
* [ErrCode: 77, Reason: error setting certificate verify locations](https://curl-cffi.readthedocs.io/en/v0.7.2/faq.html#errcode-77-reason-error-setting-certificate-verify-locations)
* [How to use with fiddler/charles to intercept content](https://curl-cffi.readthedocs.io/en/v0.7.2/faq.html#how-to-use-with-fiddler-charles-to-intercept-content)
* [ErrCode: 92, Reason: ‘HTTP/2 stream 0 was not closed cleanly: PROTOCOL\_ERROR (err 1)’](https://curl-cffi.readthedocs.io/en/v0.7.2/faq.html#errcode-92-reason-http-2-stream-0-was-not-closed-cleanly-protocol-error-err-1)
* [Packaging with PyInstaller](https://curl-cffi.readthedocs.io/en/v0.7.2/faq.html#packaging-with-pyinstaller)
* [How to set proxy?](https://curl-cffi.readthedocs.io/en/v0.7.2/faq.html#how-to-set-proxy)
* [How to change the order of headers?](https://curl-cffi.readthedocs.io/en/v0.7.2/faq.html#how-to-change-the-order-of-headers)
* [API References](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html)
* [curl low levl APIs](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl-low-levl-apis)
* [requests API](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#requests-api)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.7.2/changelog.html)
* [v0.7](https://curl-cffi.readthedocs.io/en/v0.7.2/changelog.html#v0-7)
* [v0.6](https://curl-cffi.readthedocs.io/en/v0.7.2/changelog.html#v0-6)
* [v0.5](https://curl-cffi.readthedocs.io/en/v0.7.2/changelog.html#v0-5)
* [v0.4](https://curl-cffi.readthedocs.io/en/v0.7.2/changelog.html#v0-4)
* [v0.3](https://curl-cffi.readthedocs.io/en/v0.7.2/changelog.html#v0-3)
[Discuss on Telegram](https://t.me/+lL9n33eZp480MGM1)
curl\_cffi is a Python binding for [curl-impersonate](https://github.com/lexiforest/curl-impersonate)
via [cffi](https://cffi.readthedocs.io/en/latest/)
.
Unlike other pure Python http clients like `httpx` or `requests`, `curl_cffi` can impersonate browsers’ TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try.
* * *
[](https://scrapfly.io/?utm_source=github&utm_medium=sponsoring&utm_campaign=curl_cffi)
[Scrapfly](https://scrapfly.io/?utm_source=github&utm_medium=sponsoring&utm_campaign=curl_cffi)
is an enterprise-grade solution providing Web Scraping API that aims to simplify the scraping process by managing everything: real browser rendering, rotating proxies, and fingerprints (TLS, HTTP, browser) to bypass all major anti-bots. Scrapfly also unlocks the observability by providing an analytical dashboard and measuring the success rate/block rate in details.
Scrapfly is a good solution if you are looking for a cloud-managed solution for `curl_cffi`. If you are managing TLS/HTTP fingerprint by yourself with `curl_cffi`, they also maintain a [curl to python converter](https://scrapfly.io/web-scraping-tools/curl-python/curl_cffi)
.
* * *
Features[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/#features "Link to this heading")
-----------------------------------------------------------------------------------------
* Supports JA3/TLS and http2 fingerprints impersonation.
* Much faster than requests/httpx, on par with aiohttp/pycurl, see [benchmarks](https://github.com/lexiforest/curl_cffi/tree/main/benchmark)
.
* Mimics 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 websocket.
| | | | | | |
| --- | --- | --- | --- | --- | --- |Feature matrix[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/#id3 "Link to this table")
| | requests | aiohttp | httpx | pycurl | curl\_cffi |
| --- | --- | --- | --- | --- | --- |
| http2 | ❌ | ❌ | ✅ | ✅ | ✅ |
| sync | ✅ | ❌ | ✅ | ✅ | ✅ |
| async | ❌ | ✅ | ✅ | ❌ | ✅ |
| websocket | ❌ | ✅ | ❌ | ❌ | ✅ |
| fingerprints | ❌ | ❌ | ❌ | ❌ | ✅ |
| speed | 🐇 | 🐇🐇 | 🐇 | 🐇🐇 | 🐇🐇 |
Install[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/#install "Link to this heading")
---------------------------------------------------------------------------------------
pip install curl\_cffi \--upgrade
For more details, see [Install](https://curl-cffi.readthedocs.io/en/v0.7.2/install.html)
.
Basic Usage[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/#basic-usage "Link to this heading")
-----------------------------------------------------------------------------------------------
### requests-like[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/#requests-like "Link to this heading")
from curl\_cffi import requests
url \= "https://tools.scrapfly.io/api/fp/ja3"
\# Notice the impersonate parameter
r \= requests.get("https://tools.scrapfly.io/api/fp/ja3", impersonate\="chrome110")
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 \= requests.get("https://tools.scrapfly.io/api/fp/ja3", impersonate\="chrome")
\# http/socks proxies are supported
proxies \= {"https": "http://localhost:3128"}
r \= requests.get("https://tools.scrapfly.io/api/fp/ja3", impersonate\="chrome110", proxies\=proxies)
proxies \= {"https": "socks://localhost:3128"}
r \= requests.get("https://tools.scrapfly.io/api/fp/ja3", impersonate\="chrome110", proxies\=proxies)
### Sessions[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/#sessions "Link to this heading")
s \= requests.Session()
\# httpbin is a http test website
s.get("https://httpbin.org/cookies/set/foo/bar")
print(s.cookies)
\# \]>
r \= s.get("https://httpbin.org/cookies")
print(r.json())
\# {'cookies': {'foo': 'bar'}}
### asyncio[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/#asyncio "Link to this heading")
from curl\_cffi.requests import AsyncSession
async with AsyncSession() as s:
r \= await s.get("https://example.com")
More concurrency:
import asyncio
from curl\_cffi.requests 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)
### WebSockets[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/#websockets "Link to this heading")
from curl\_cffi.requests import Session, WebSocket
def on\_message(ws: WebSocket, message):
print(message)
with Session() as s:
ws \= s.ws\_connect(
"wss://api.gemini.com/v1/marketdata/BTCUSD",
on\_message\=on\_message,
)
ws.run\_forever()
Sponsor[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/#sponsor "Link to this heading")
---------------------------------------------------------------------------------------
Click [here](https://buymeacoffee.com/yifei)
to buy me a coffee.
### Bypass Cloudflare with API[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/#bypass-cloudflare-with-api "Link to this heading")
[](https://yescaptcha.com/i/stfnIO)
[Yescaptcha](https://yescaptcha.com/i/stfnIO)
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.
### ScrapeNinja[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/#scrapeninja "Link to this heading")
[](https://scrapeninja.net/?utm_source=github&utm_medium=banner&utm_campaign=cffi)
[ScrapeNinja](https://scrapeninja.net/?utm_source=github&utm_medium=banner&utm_campaign=cffi)
is a web scraping API with two engines: fast, with high performance and TLS fingerprint; and slower with a real browser under the hood.
ScrapeNinja handles headless browsers, proxies, timeouts, retries, and helps with data extraction, so you can just get the data in JSON. Rotating proxies are available out of the box on all subscription plans.
Indices and tables[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/#indices-and-tables "Link to this heading")
=============================================================================================================
* [Index](https://curl-cffi.readthedocs.io/en/v0.7.2/genindex.html)
* [Module Index](https://curl-cffi.readthedocs.io/en/v0.7.2/py-modindex.html)
* [Search Page](https://curl-cffi.readthedocs.io/en/v0.7.2/search.html)
[curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.2/#)
===========================================================
### Navigation
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.7.2/install.html)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.7.2/impersonate.html)
* [Cookies](https://curl-cffi.readthedocs.io/en/v0.7.2/cookies.html)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.7.2/advanced.html)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.7.2/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.7.2/faq.html)
* [API References](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.7.2/changelog.html)
### Related Topics
* [Documentation overview](https://curl-cffi.readthedocs.io/en/v0.7.2/#)
* Next: [Install](https://curl-cffi.readthedocs.io/en/v0.7.2/install.html "next chapter")
---
# Welcome to curl_cffi’s documentation! — curl_cffi documentation
Welcome to curl\_cffi’s documentation
===================================================================================================================================================
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.7.1/install.html)
* [Via pip](https://curl-cffi.readthedocs.io/en/v0.7.1/install.html#via-pip)
* [Beta versions](https://curl-cffi.readthedocs.io/en/v0.7.1/install.html#beta-versions)
* [Latest](https://curl-cffi.readthedocs.io/en/v0.7.1/install.html#latest)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.7.1/impersonate.html)
* [Supported browser versions](https://curl-cffi.readthedocs.io/en/v0.7.1/impersonate.html#supported-browser-versions)
* [Which version to use?](https://curl-cffi.readthedocs.io/en/v0.7.1/impersonate.html#which-version-to-use)
* [How to use my own fingerprints other than the builtin ones? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.7.1/impersonate.html#how-to-use-my-own-fingerprints-other-than-the-builtin-ones-e-g-okhttp)
* [Should I randomize my fingerprints for each request?](https://curl-cffi.readthedocs.io/en/v0.7.1/impersonate.html#should-i-randomize-my-fingerprints-for-each-request)
* [Can I change JavaScript fingerprints with this library?](https://curl-cffi.readthedocs.io/en/v0.7.1/impersonate.html#can-i-change-javascript-fingerprints-with-this-library)
* [Cookies](https://curl-cffi.readthedocs.io/en/v0.7.1/cookies.html)
* [How to save and load cookies](https://curl-cffi.readthedocs.io/en/v0.7.1/cookies.html#how-to-save-and-load-cookies)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.7.1/advanced.html)
* [low-level curl API](https://curl-cffi.readthedocs.io/en/v0.7.1/advanced.html#low-level-curl-api)
* [scrapy integrations](https://curl-cffi.readthedocs.io/en/v0.7.1/advanced.html#scrapy-integrations)
* [Using with eventlet/gevent](https://curl-cffi.readthedocs.io/en/v0.7.1/advanced.html#using-with-eventlet-gevent)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.7.1/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.7.1/faq.html)
* [Why does the JA3 fingerprints change for Chrome 110+ impersonation?](https://curl-cffi.readthedocs.io/en/v0.7.1/faq.html#why-does-the-ja3-fingerprints-change-for-chrome-110-impersonation)
* [Can I bypass Cloudflare with this project? or any other specific site.](https://curl-cffi.readthedocs.io/en/v0.7.1/faq.html#can-i-bypass-cloudflare-with-this-project-or-any-other-specific-site)
* [I’m getting certs errors](https://curl-cffi.readthedocs.io/en/v0.7.1/faq.html#i-m-getting-certs-errors)
* [ErrCode: 77, Reason: error setting certificate verify locations](https://curl-cffi.readthedocs.io/en/v0.7.1/faq.html#errcode-77-reason-error-setting-certificate-verify-locations)
* [How to use with fiddler/charles to intercept content](https://curl-cffi.readthedocs.io/en/v0.7.1/faq.html#how-to-use-with-fiddler-charles-to-intercept-content)
* [ErrCode: 92, Reason: ‘HTTP/2 stream 0 was not closed cleanly: PROTOCOL\_ERROR (err 1)’](https://curl-cffi.readthedocs.io/en/v0.7.1/faq.html#errcode-92-reason-http-2-stream-0-was-not-closed-cleanly-protocol-error-err-1)
* [Packaging with PyInstaller](https://curl-cffi.readthedocs.io/en/v0.7.1/faq.html#packaging-with-pyinstaller)
* [How to set proxy?](https://curl-cffi.readthedocs.io/en/v0.7.1/faq.html#how-to-set-proxy)
* [How to change the order of headers?](https://curl-cffi.readthedocs.io/en/v0.7.1/faq.html#how-to-change-the-order-of-headers)
* [API References](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html)
* [curl low levl APIs](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl-low-levl-apis)
* [requests API](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#requests-api)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.7.1/changelog.html)
* [v0.7](https://curl-cffi.readthedocs.io/en/v0.7.1/changelog.html#v0-7)
* [v0.6](https://curl-cffi.readthedocs.io/en/v0.7.1/changelog.html#v0-6)
* [v0.5](https://curl-cffi.readthedocs.io/en/v0.7.1/changelog.html#v0-5)
* [v0.4](https://curl-cffi.readthedocs.io/en/v0.7.1/changelog.html#v0-4)
* [v0.3](https://curl-cffi.readthedocs.io/en/v0.7.1/changelog.html#v0-3)
[中文 README](https://github.com/yifeikong/curl_cffi/blob/main/README-zh.md)
| [Discuss on Telegram](https://t.me/+lL9n33eZp480MGM1)
curl\_cffi is a Python binding for [curl-impersonate](https://github.com/yifeikong/curl-impersonate)
via [cffi](https://cffi.readthedocs.io/en/latest/)
.
Unlike other pure Python http clients like `httpx` or `requests`, `curl_cffi` can impersonate browsers’ TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try.
* * *
[](https://scrapfly.io/?utm_source=github&utm_medium=sponsoring&utm_campaign=curl_cffi)
[Scrapfly](https://scrapfly.io/?utm_source=github&utm_medium=sponsoring&utm_campaign=curl_cffi)
is an enterprise-grade solution providing Web Scraping API that aims to simplify the scraping process by managing everything: real browser rendering, rotating proxies, and fingerprints (TLS, HTTP, browser) to bypass all major anti-bots. Scrapfly also unlocks the observability by providing an analytical dashboard and measuring the success rate/block rate in details.
Scrapfly is a good solution if you are looking for a cloud-managed solution for `curl_cffi`. If you are managing TLS/HTTP fingerprint by yourself with `curl_cffi`, they also maintain a [curl to python converter](https://scrapfly.io/web-scraping-tools/curl-python/curl_cffi)
.
* * *
Features[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/#features "Link to this heading")
-----------------------------------------------------------------------------------------
* Supports JA3/TLS and http2 fingerprints impersonation.
* Much faster than requests/httpx, on par with aiohttp/pycurl, see [benchmarks](https://github.com/yifeikong/curl_cffi/tree/main/benchmark)
.
* Mimics 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 websocket.
| | | | | | |
| --- | --- | --- | --- | --- | --- |Feature matrix[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/#id3 "Link to this table")
| | requests | aiohttp | httpx | pycurl | curl\_cffi |
| --- | --- | --- | --- | --- | --- |
| http2 | ❌ | ❌ | ✅ | ✅ | ✅ |
| sync | ✅ | ❌ | ✅ | ✅ | ✅ |
| async | ❌ | ✅ | ✅ | ❌ | ✅ |
| websocket | ❌ | ✅ | ❌ | ❌ | ✅ |
| fingerprints | ❌ | ❌ | ❌ | ❌ | ✅ |
| speed | 🐇 | 🐇🐇 | 🐇 | 🐇🐇 | 🐇🐇 |
Install[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/#install "Link to this heading")
---------------------------------------------------------------------------------------
pip install curl\_cffi \--upgrade
For more details, see [Install](https://curl-cffi.readthedocs.io/en/v0.7.1/install.html)
.
Basic Usage[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/#basic-usage "Link to this heading")
-----------------------------------------------------------------------------------------------
### requests-like[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/#requests-like "Link to this heading")
from curl\_cffi import requests
url \= "https://tools.scrapfly.io/api/fp/ja3"
\# Notice the impersonate parameter
r \= requests.get("https://tools.scrapfly.io/api/fp/ja3", impersonate\="chrome110")
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 \= requests.get("https://tools.scrapfly.io/api/fp/ja3", impersonate\="chrome")
\# http/socks proxies are supported
proxies \= {"https": "http://localhost:3128"}
r \= requests.get("https://tools.scrapfly.io/api/fp/ja3", impersonate\="chrome110", proxies\=proxies)
proxies \= {"https": "socks://localhost:3128"}
r \= requests.get("https://tools.scrapfly.io/api/fp/ja3", impersonate\="chrome110", proxies\=proxies)
### Sessions[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/#sessions "Link to this heading")
s \= requests.Session()
\# httpbin is a http test website
s.get("https://httpbin.org/cookies/set/foo/bar")
print(s.cookies)
\# \]>
r \= s.get("https://httpbin.org/cookies")
print(r.json())
\# {'cookies': {'foo': 'bar'}}
### asyncio[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/#asyncio "Link to this heading")
from curl\_cffi.requests import AsyncSession
async with AsyncSession() as s:
r \= await s.get("https://example.com")
More concurrency:
import asyncio
from curl\_cffi.requests 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)
### WebSockets[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/#websockets "Link to this heading")
from curl\_cffi.requests import Session, WebSocket
def on\_message(ws: WebSocket, message):
print(message)
with Session() as s:
ws \= s.ws\_connect(
"wss://api.gemini.com/v1/marketdata/BTCUSD",
on\_message\=on\_message,
)
ws.run\_forever()
Sponsor[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/#sponsor "Link to this heading")
---------------------------------------------------------------------------------------
Click [here](https://buymeacoffee.com/yifei)
to buy me a coffee.
### Bypass Cloudflare with API[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/#bypass-cloudflare-with-api "Link to this heading")
[](https://yescaptcha.com/i/stfnIO)
[Yescaptcha](https://yescaptcha.com/i/stfnIO)
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.
### ScrapeNinja[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/#scrapeninja "Link to this heading")
[](https://scrapeninja.net/?utm_source=github&utm_medium=banner&utm_campaign=cffi)
[ScrapeNinja](https://scrapeninja.net/?utm_source=github&utm_medium=banner&utm_campaign=cffi)
is a web scraping API with two engines: fast, with high performance and TLS fingerprint; and slower with a real browser under the hood.
ScrapeNinja handles headless browsers, proxies, timeouts, retries, and helps with data extraction, so you can just get the data in JSON. Rotating proxies are available out of the box on all subscription plans.
Indices and tables[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/#indices-and-tables "Link to this heading")
=============================================================================================================
* [Index](https://curl-cffi.readthedocs.io/en/v0.7.1/genindex.html)
* [Module Index](https://curl-cffi.readthedocs.io/en/v0.7.1/py-modindex.html)
* [Search Page](https://curl-cffi.readthedocs.io/en/v0.7.1/search.html)
[curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.1/#)
===========================================================
### Navigation
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.7.1/install.html)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.7.1/impersonate.html)
* [Cookies](https://curl-cffi.readthedocs.io/en/v0.7.1/cookies.html)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.7.1/advanced.html)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.7.1/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.7.1/faq.html)
* [API References](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.7.1/changelog.html)
### Related Topics
* [Documentation overview](https://curl-cffi.readthedocs.io/en/v0.7.1/#)
* Next: [Install](https://curl-cffi.readthedocs.io/en/v0.7.1/install.html "next chapter")
### Quick search
---
# Welcome to curl_cffi’s documentation! — curl_cffi documentation
Welcome to curl\_cffi’s documentation
===================================================================================================================================================
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.7.0/install.html)
* [Via pip](https://curl-cffi.readthedocs.io/en/v0.7.0/install.html#via-pip)
* [Beta versions](https://curl-cffi.readthedocs.io/en/v0.7.0/install.html#beta-versions)
* [Latest](https://curl-cffi.readthedocs.io/en/v0.7.0/install.html#latest)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.7.0/impersonate.html)
* [Supported browser versions](https://curl-cffi.readthedocs.io/en/v0.7.0/impersonate.html#supported-browser-versions)
* [Which version to use?](https://curl-cffi.readthedocs.io/en/v0.7.0/impersonate.html#which-version-to-use)
* [How to use my own fingerprints other than the builtin ones? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.7.0/impersonate.html#how-to-use-my-own-fingerprints-other-than-the-builtin-ones-e-g-okhttp)
* [Should I randomize my fingerprints for each request?](https://curl-cffi.readthedocs.io/en/v0.7.0/impersonate.html#should-i-randomize-my-fingerprints-for-each-request)
* [Can I change JavaScript fingerprints with this library?](https://curl-cffi.readthedocs.io/en/v0.7.0/impersonate.html#can-i-change-javascript-fingerprints-with-this-library)
* [Cookies](https://curl-cffi.readthedocs.io/en/v0.7.0/cookies.html)
* [How to save and load cookies](https://curl-cffi.readthedocs.io/en/v0.7.0/cookies.html#how-to-save-and-load-cookies)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.7.0/advanced.html)
* [low-level curl API](https://curl-cffi.readthedocs.io/en/v0.7.0/advanced.html#low-level-curl-api)
* [scrapy integrations](https://curl-cffi.readthedocs.io/en/v0.7.0/advanced.html#scrapy-integrations)
* [Using with eventlet/gevent](https://curl-cffi.readthedocs.io/en/v0.7.0/advanced.html#using-with-eventlet-gevent)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.7.0/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.7.0/faq.html)
* [Why does the JA3 fingerprints change for Chrome 110+ impersonation?](https://curl-cffi.readthedocs.io/en/v0.7.0/faq.html#why-does-the-ja3-fingerprints-change-for-chrome-110-impersonation)
* [Can I bypass Cloudflare with this project? or any other specific site.](https://curl-cffi.readthedocs.io/en/v0.7.0/faq.html#can-i-bypass-cloudflare-with-this-project-or-any-other-specific-site)
* [I’m getting certs errors](https://curl-cffi.readthedocs.io/en/v0.7.0/faq.html#i-m-getting-certs-errors)
* [ErrCode: 77, Reason: error setting certificate verify locations](https://curl-cffi.readthedocs.io/en/v0.7.0/faq.html#errcode-77-reason-error-setting-certificate-verify-locations)
* [How to use with fiddler/charles to intercept content](https://curl-cffi.readthedocs.io/en/v0.7.0/faq.html#how-to-use-with-fiddler-charles-to-intercept-content)
* [ErrCode: 92, Reason: ‘HTTP/2 stream 0 was not closed cleanly: PROTOCOL\_ERROR (err 1)’](https://curl-cffi.readthedocs.io/en/v0.7.0/faq.html#errcode-92-reason-http-2-stream-0-was-not-closed-cleanly-protocol-error-err-1)
* [Packaging with PyInstaller](https://curl-cffi.readthedocs.io/en/v0.7.0/faq.html#packaging-with-pyinstaller)
* [How to set proxy?](https://curl-cffi.readthedocs.io/en/v0.7.0/faq.html#how-to-set-proxy)
* [How to change the order of headers?](https://curl-cffi.readthedocs.io/en/v0.7.0/faq.html#how-to-change-the-order-of-headers)
* [API References](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html)
* [curl low levl APIs](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl-low-levl-apis)
* [requests API](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#requests-api)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.7.0/changelog.html)
* [v0.7](https://curl-cffi.readthedocs.io/en/v0.7.0/changelog.html#v0-7)
* [v0.6](https://curl-cffi.readthedocs.io/en/v0.7.0/changelog.html#v0-6)
* [v0.5](https://curl-cffi.readthedocs.io/en/v0.7.0/changelog.html#v0-5)
* [v0.4](https://curl-cffi.readthedocs.io/en/v0.7.0/changelog.html#v0-4)
* [v0.3](https://curl-cffi.readthedocs.io/en/v0.7.0/changelog.html#v0-3)
[中文 README](https://github.com/yifeikong/curl_cffi/blob/main/README-zh.md)
| [Discuss on Telegram](https://t.me/+lL9n33eZp480MGM1)
curl\_cffi is a Python binding for [curl-impersonate](https://github.com/yifeikong/curl-impersonate)
via [cffi](https://cffi.readthedocs.io/en/latest/)
.
Unlike other pure Python http clients like `httpx` or `requests`, `curl_cffi` can impersonate browsers’ TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try.
* * *
[](https://scrapfly.io/?utm_source=github&utm_medium=sponsoring&utm_campaign=curl_cffi)
[Scrapfly](https://scrapfly.io/?utm_source=github&utm_medium=sponsoring&utm_campaign=curl_cffi)
is an enterprise-grade solution providing Web Scraping API that aims to simplify the scraping process by managing everything: real browser rendering, rotating proxies, and fingerprints (TLS, HTTP, browser) to bypass all major anti-bots. Scrapfly also unlocks the observability by providing an analytical dashboard and measuring the success rate/block rate in details.
Scrapfly is a good solution if you are looking for a cloud-managed solution for `curl_cffi`. If you are managing TLS/HTTP fingerprint by yourself with `curl_cffi`, they also maintain a [curl to python converter](https://scrapfly.io/web-scraping-tools/curl-python/curl_cffi)
.
* * *
Features[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/#features "Link to this heading")
-----------------------------------------------------------------------------------------
* Supports JA3/TLS and http2 fingerprints impersonation.
* Much faster than requests/httpx, on par with aiohttp/pycurl, see [benchmarks](https://github.com/yifeikong/curl_cffi/tree/main/benchmark)
.
* Mimics 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 websocket.
| | | | | | |
| --- | --- | --- | --- | --- | --- |Feature matrix[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/#id3 "Link to this table")
| | requests | aiohttp | httpx | pycurl | curl\_cffi |
| --- | --- | --- | --- | --- | --- |
| http2 | ❌ | ❌ | ✅ | ✅ | ✅ |
| sync | ✅ | ❌ | ✅ | ✅ | ✅ |
| async | ❌ | ✅ | ✅ | ❌ | ✅ |
| websocket | ❌ | ✅ | ❌ | ❌ | ✅ |
| fingerprints | ❌ | ❌ | ❌ | ❌ | ✅ |
| speed | 🐇 | 🐇🐇 | 🐇 | 🐇🐇 | 🐇🐇 |
Install[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/#install "Link to this heading")
---------------------------------------------------------------------------------------
pip install curl\_cffi \--upgrade
For more details, see [Install](https://curl-cffi.readthedocs.io/en/v0.7.0/install.html)
.
Basic Usage[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/#basic-usage "Link to this heading")
-----------------------------------------------------------------------------------------------
### requests-like[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/#requests-like "Link to this heading")
from curl\_cffi import requests
url \= "https://tools.scrapfly.io/api/fp/ja3"
\# Notice the impersonate parameter
r \= requests.get("https://tools.scrapfly.io/api/fp/ja3", impersonate\="chrome110")
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 \= requests.get("https://tools.scrapfly.io/api/fp/ja3", impersonate\="chrome")
\# http/socks proxies are supported
proxies \= {"https": "http://localhost:3128"}
r \= requests.get("https://tools.scrapfly.io/api/fp/ja3", impersonate\="chrome110", proxies\=proxies)
proxies \= {"https": "socks://localhost:3128"}
r \= requests.get("https://tools.scrapfly.io/api/fp/ja3", impersonate\="chrome110", proxies\=proxies)
### Sessions[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/#sessions "Link to this heading")
s \= requests.Session()
\# httpbin is a http test website
s.get("https://httpbin.org/cookies/set/foo/bar")
print(s.cookies)
\# \]>
r \= s.get("https://httpbin.org/cookies")
print(r.json())
\# {'cookies': {'foo': 'bar'}}
### asyncio[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/#asyncio "Link to this heading")
from curl\_cffi.requests import AsyncSession
async with AsyncSession() as s:
r \= await s.get("https://example.com")
More concurrency:
import asyncio
from curl\_cffi.requests 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)
### WebSockets[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/#websockets "Link to this heading")
from curl\_cffi.requests import Session, WebSocket
def on\_message(ws: WebSocket, message):
print(message)
with Session() as s:
ws \= s.ws\_connect(
"wss://api.gemini.com/v1/marketdata/BTCUSD",
on\_message\=on\_message,
)
ws.run\_forever()
Sponsor[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/#sponsor "Link to this heading")
---------------------------------------------------------------------------------------
Click [here](https://buymeacoffee.com/yifei)
to buy me a coffee.
### Bypass Cloudflare with API[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/#bypass-cloudflare-with-api "Link to this heading")
[](https://yescaptcha.com/i/stfnIO)
[Yescaptcha](https://yescaptcha.com/i/stfnIO)
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.
### ScrapeNinja[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/#scrapeninja "Link to this heading")
[](https://scrapeninja.net/?utm_source=github&utm_medium=banner&utm_campaign=cffi)
[ScrapeNinja](https://scrapeninja.net/?utm_source=github&utm_medium=banner&utm_campaign=cffi)
is a web scraping API with two engines: fast, with high performance and TLS fingerprint; and slower with a real browser under the hood.
ScrapeNinja handles headless browsers, proxies, timeouts, retries, and helps with data extraction, so you can just get the data in JSON. Rotating proxies are available out of the box on all subscription plans.
Indices and tables[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/#indices-and-tables "Link to this heading")
=============================================================================================================
* [Index](https://curl-cffi.readthedocs.io/en/v0.7.0/genindex.html)
* [Module Index](https://curl-cffi.readthedocs.io/en/v0.7.0/py-modindex.html)
* [Search Page](https://curl-cffi.readthedocs.io/en/v0.7.0/search.html)
[curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.0/#)
===========================================================
### Navigation
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.7.0/install.html)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.7.0/impersonate.html)
* [Cookies](https://curl-cffi.readthedocs.io/en/v0.7.0/cookies.html)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.7.0/advanced.html)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.7.0/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.7.0/faq.html)
* [API References](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.7.0/changelog.html)
### Related Topics
* [Documentation overview](https://curl-cffi.readthedocs.io/en/v0.7.0/#)
* Next: [Install](https://curl-cffi.readthedocs.io/en/v0.7.0/install.html "next chapter")
### Quick search
---
# Welcome to curl_cffi’s documentation! — curl_cffi documentation
Welcome to curl\_cffi’s documentation
====================================================================================================================================================
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.11.0/install.html)
* [Via pip](https://curl-cffi.readthedocs.io/en/v0.11.0/install.html#via-pip)
* [Beta versions](https://curl-cffi.readthedocs.io/en/v0.11.0/install.html#beta-versions)
* [Latest](https://curl-cffi.readthedocs.io/en/v0.11.0/install.html#latest)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.11.0/impersonate.html)
* [Supported browser versions](https://curl-cffi.readthedocs.io/en/v0.11.0/impersonate.html#supported-browser-versions)
* [Which version to use?](https://curl-cffi.readthedocs.io/en/v0.11.0/impersonate.html#which-version-to-use)
* [How to use my own fingerprints other than the builtin ones? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.11.0/impersonate.html#how-to-use-my-own-fingerprints-other-than-the-builtin-ones-e-g-okhttp)
* [Should I randomize my fingerprints for each request?](https://curl-cffi.readthedocs.io/en/v0.11.0/impersonate.html#should-i-randomize-my-fingerprints-for-each-request)
* [Can I change JavaScript fingerprints with this library?](https://curl-cffi.readthedocs.io/en/v0.11.0/impersonate.html#can-i-change-javascript-fingerprints-with-this-library)
* [Cookies](https://curl-cffi.readthedocs.io/en/v0.11.0/cookies.html)
* [How to save and load cookies](https://curl-cffi.readthedocs.io/en/v0.11.0/cookies.html#how-to-save-and-load-cookies)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.11.0/advanced.html)
* [Low-level curl API](https://curl-cffi.readthedocs.io/en/v0.11.0/advanced.html#low-level-curl-api)
* [Scrapy integrations](https://curl-cffi.readthedocs.io/en/v0.11.0/advanced.html#scrapy-integrations)
* [Using with eventlet/gevent](https://curl-cffi.readthedocs.io/en/v0.11.0/advanced.html#using-with-eventlet-gevent)
* [As a urllib3/requests adapter](https://curl-cffi.readthedocs.io/en/v0.11.0/advanced.html#as-a-urllib3-requests-adapter)
* [As a httpx transport](https://curl-cffi.readthedocs.io/en/v0.11.0/advanced.html#as-a-httpx-transport)
* [Keeping session alive in http/2](https://curl-cffi.readthedocs.io/en/v0.11.0/advanced.html#keeping-session-alive-in-http-2)
* [Exceptions](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html)
* [Exceptions](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#id1)
* [Warnings](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#warnings)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.11.0/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.11.0/faq.html)
* [Why does the JA3 fingerprints change for Chrome 110+ impersonation?](https://curl-cffi.readthedocs.io/en/v0.11.0/faq.html#why-does-the-ja3-fingerprints-change-for-chrome-110-impersonation)
* [Can I bypass Cloudflare with this project? or any other specific site.](https://curl-cffi.readthedocs.io/en/v0.11.0/faq.html#can-i-bypass-cloudflare-with-this-project-or-any-other-specific-site)
* [I’m getting certs errors](https://curl-cffi.readthedocs.io/en/v0.11.0/faq.html#i-m-getting-certs-errors)
* [ErrCode: 77, Reason: error setting certificate verify locations](https://curl-cffi.readthedocs.io/en/v0.11.0/faq.html#errcode-77-reason-error-setting-certificate-verify-locations)
* [How to use with fiddler/charles to intercept content](https://curl-cffi.readthedocs.io/en/v0.11.0/faq.html#how-to-use-with-fiddler-charles-to-intercept-content)
* [ErrCode: 92, Reason: ‘HTTP/2 stream 0 was not closed cleanly: PROTOCOL\_ERROR (err 1)’](https://curl-cffi.readthedocs.io/en/v0.11.0/faq.html#errcode-92-reason-http-2-stream-0-was-not-closed-cleanly-protocol-error-err-1)
* [Packaging with PyInstaller](https://curl-cffi.readthedocs.io/en/v0.11.0/faq.html#packaging-with-pyinstaller)
* [How to set proxy?](https://curl-cffi.readthedocs.io/en/v0.11.0/faq.html#how-to-set-proxy)
* [How to change the order of headers?](https://curl-cffi.readthedocs.io/en/v0.11.0/faq.html#how-to-change-the-order-of-headers)
* [API References](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html)
* [curl low levl APIs](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl-low-levl-apis)
* [requests API](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#requests-api)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.11.0/changelog.html)
* [v0.11](https://curl-cffi.readthedocs.io/en/v0.11.0/changelog.html#v0-11)
* [v0.10](https://curl-cffi.readthedocs.io/en/v0.11.0/changelog.html#v0-10)
* [v0.9](https://curl-cffi.readthedocs.io/en/v0.11.0/changelog.html#v0-9)
* [v0.8](https://curl-cffi.readthedocs.io/en/v0.11.0/changelog.html#v0-8)
* [v0.7](https://curl-cffi.readthedocs.io/en/v0.11.0/changelog.html#v0-7)
* [v0.6](https://curl-cffi.readthedocs.io/en/v0.11.0/changelog.html#v0-6)
* [v0.5](https://curl-cffi.readthedocs.io/en/v0.11.0/changelog.html#v0-5)
* [v0.4](https://curl-cffi.readthedocs.io/en/v0.11.0/changelog.html#v0-4)
* [v0.3](https://curl-cffi.readthedocs.io/en/v0.11.0/changelog.html#v0-3)
[Discuss on Telegram](https://t.me/+lL9n33eZp480MGM1)
curl\_cffi is a Python binding for [\`curl-impersonate fork\`\_](https://curl-cffi.readthedocs.io/en/v0.11.0/#id5)
via [cffi](https://cffi.readthedocs.io/en/latest/)
. For commercial support, visit [impersonate.pro](https://impersonate.pro/)
.
Unlike other pure Python http clients like `httpx` or `requests`, `curl_cffi` can impersonate browsers’ TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try.
Sponsors[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/#sponsors "Link to this heading")
------------------------------------------------------------------------------------------
### SerpAPI[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/#serpapi "Link to this heading")
[](https://serpapi.com/)
Scrape Google and other search engines from [SerpApi](https://serpapi.com/)
’s fast, easy, and complete API. 0.66s average response time (≤ 0.5s for Ludicrous Speed Max accounts), 99.95% SLAs, pay for successful responses only.
### Bypass Cloudflare with API[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/#bypass-cloudflare-with-api "Link to this heading")
[](https://yescaptcha.com/i/stfnIO)
[Yescaptcha](https://yescaptcha.com/i/stfnIO)
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.
### Easy Captcha Bypass for Scraping[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/#easy-captcha-bypass-for-scraping "Link to this heading")
[](https://www.capsolver.com/?utm_source=github&utm_medium=banner_repo&utm_campaign=scraping&utm_term=curl_cffi)
[CapSolver](https://www.capsolver.com/?utm_source=github&utm_medium=banner_repo&utm_campaign=scraping&utm_term=curl_cffi)
is an AI-powered tool that easily bypasses Captchas, allowing uninterrupted access to public data. It supports a variety of Captchas and works seamlessly with `curl_cffi`, Puppeteer, Playwright, and more. Fast, reliable, and cost-effective. Plus, `curl_cffi` users can use the code **“CURL”** to get an extra 6% balance! and register [here](https://dashboard.capsolver.com/passport/?utm_source=github&utm_medium=banner_repo&utm_campaign=scraping&utm_term=curl_cffi)
You can also click [here](https://buymeacoffee.com/yifei)
to buy me a coffee.
* * *
Features[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/#features "Link to this heading")
------------------------------------------------------------------------------------------
* 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 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 & 3.0, which requests does not.
* Supports websocket.
| | | | | | |
| --- | --- | --- | --- | --- | --- |Feature matrix[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/#id4 "Link to this table")
| | requests | aiohttp | httpx | pycurl | curl\_cffi |
| --- | --- | --- | --- | --- | --- |
| http2 | ❌ | ❌ | ✅ | ✅ | ✅ |
| http3 | ❌ | ❌ | ❌ | ☑️ | ☑️ |
| sync | ✅ | ❌ | ✅ | ✅ | ✅ |
| async | ❌ | ✅ | ✅ | ❌ | ✅ |
| websocket | ❌ | ✅ | ❌ | ❌ | ✅ |
| fingerprints | ❌ | ❌ | ❌ | ❌ | ✅ |
| speed | 🐇 | 🐇🐇 | 🐇 | 🐇🐇 | 🐇🐇 |
Notes:
1. For pycurl, you need a http/3 enabled libcurl to make it work, while curl\_cffi packages libcurl-impersonate inside Python wheels.
2. Since v0.11.0. However, only Linux and macOS are supported, Windows is not supported due to failed building of ngtcp2.
Install[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/#install "Link to this heading")
----------------------------------------------------------------------------------------
pip install curl\_cffi \--upgrade
For more details, see [Install](https://curl-cffi.readthedocs.io/en/v0.11.0/install.html)
.
Basic Usage[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/#basic-usage "Link to this heading")
------------------------------------------------------------------------------------------------
### requests-like[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/#requests-like "Link to this heading")
import curl\_cffi
url \= "https://tls.browserleaks.com/json"
\# Notice the impersonate parameter
r \= curl\_cffi.get("https://tls.browserleaks.com/json", impersonate\="chrome110")
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")
\# http/socks proxies are supported
proxies \= {"https": "http://localhost:3128"}
r \= curl\_cffi.get("https://tls.browserleaks.com/json", impersonate\="chrome110", proxies\=proxies)
proxies \= {"https": "socks://localhost:3128"}
r \= curl\_cffi.get("https://tls.browserleaks.com/json", impersonate\="chrome110", proxies\=proxies)
### Sessions[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/#sessions "Link to this heading")
s \= curl\_cffi.Session()
\# httpbin is a http test website
s.get("https://httpbin.org/cookies/set/foo/bar")
print(s.cookies)
\# \]>
r \= s.get("https://httpbin.org/cookies")
print(r.json())
\# {'cookies': {'foo': 'bar'}}
### asyncio[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/#asyncio "Link to this heading")
async with curl\_cffi.AsyncSession() as s:
r \= await s.get("https://example.com")
More concurrency:
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)
### WebSockets[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/#websockets "Link to this heading")
from curl\_cffi import Session, WebSocket
def on\_message(ws: WebSocket, message):
print(message)
with Session() as s:
ws \= s.ws\_connect(
"wss://api.gemini.com/v1/marketdata/BTCUSD",
on\_message\=on\_message,
)
ws.run\_forever()
\# asyncio
import asyncio
from curl\_cffi import AsyncSession
async with AsyncSession() as s:
ws \= await s.ws\_connect("wss://echo.websocket.org")
await asyncio.gather(\*\[ws.send\_str("Hello, World!") for \_ in range(10)\])
async for message in ws:
print(message)
Indices and tables[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/#indices-and-tables "Link to this heading")
==============================================================================================================
* [Index](https://curl-cffi.readthedocs.io/en/v0.11.0/genindex.html)
* [Module Index](https://curl-cffi.readthedocs.io/en/v0.11.0/py-modindex.html)
* [Search Page](https://curl-cffi.readthedocs.io/en/v0.11.0/search.html)
[curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.11.0/#)
============================================================
### Navigation
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.11.0/install.html)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.11.0/impersonate.html)
* [Cookies](https://curl-cffi.readthedocs.io/en/v0.11.0/cookies.html)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.11.0/advanced.html)
* [Exceptions](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.11.0/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.11.0/faq.html)
* [API References](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.11.0/changelog.html)
### Related Topics
* [Documentation overview](https://curl-cffi.readthedocs.io/en/v0.11.0/#)
* Next: [Install](https://curl-cffi.readthedocs.io/en/v0.11.0/install.html "next chapter")
---
# Welcome to curl_cffi’s documentation! — curl_cffi documentation
Welcome to curl\_cffi’s documentation
====================================================================================================================================================
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.11.2/install.html)
* [Via pip](https://curl-cffi.readthedocs.io/en/v0.11.2/install.html#via-pip)
* [Beta versions](https://curl-cffi.readthedocs.io/en/v0.11.2/install.html#beta-versions)
* [Latest](https://curl-cffi.readthedocs.io/en/v0.11.2/install.html#latest)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.11.2/impersonate.html)
* [Supported browser versions](https://curl-cffi.readthedocs.io/en/v0.11.2/impersonate.html#supported-browser-versions)
* [Which version to use?](https://curl-cffi.readthedocs.io/en/v0.11.2/impersonate.html#which-version-to-use)
* [How to use my own fingerprints other than the builtin ones? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.11.2/impersonate.html#how-to-use-my-own-fingerprints-other-than-the-builtin-ones-e-g-okhttp)
* [Should I randomize my fingerprints for each request?](https://curl-cffi.readthedocs.io/en/v0.11.2/impersonate.html#should-i-randomize-my-fingerprints-for-each-request)
* [Can I change JavaScript fingerprints with this library?](https://curl-cffi.readthedocs.io/en/v0.11.2/impersonate.html#can-i-change-javascript-fingerprints-with-this-library)
* [Cookies](https://curl-cffi.readthedocs.io/en/v0.11.2/cookies.html)
* [How to save and load cookies](https://curl-cffi.readthedocs.io/en/v0.11.2/cookies.html#how-to-save-and-load-cookies)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.11.2/advanced.html)
* [Low-level curl API](https://curl-cffi.readthedocs.io/en/v0.11.2/advanced.html#low-level-curl-api)
* [Scrapy integrations](https://curl-cffi.readthedocs.io/en/v0.11.2/advanced.html#scrapy-integrations)
* [Using with eventlet/gevent](https://curl-cffi.readthedocs.io/en/v0.11.2/advanced.html#using-with-eventlet-gevent)
* [As a urllib3/requests adapter](https://curl-cffi.readthedocs.io/en/v0.11.2/advanced.html#as-a-urllib3-requests-adapter)
* [As a httpx transport](https://curl-cffi.readthedocs.io/en/v0.11.2/advanced.html#as-a-httpx-transport)
* [Keeping session alive in http/2](https://curl-cffi.readthedocs.io/en/v0.11.2/advanced.html#keeping-session-alive-in-http-2)
* [Exceptions](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html)
* [Exceptions](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#id1)
* [Warnings](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#warnings)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.11.2/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.11.2/faq.html)
* [Why does the JA3 fingerprints change for Chrome 110+ impersonation?](https://curl-cffi.readthedocs.io/en/v0.11.2/faq.html#why-does-the-ja3-fingerprints-change-for-chrome-110-impersonation)
* [Can I bypass Cloudflare with this project? or any other specific site.](https://curl-cffi.readthedocs.io/en/v0.11.2/faq.html#can-i-bypass-cloudflare-with-this-project-or-any-other-specific-site)
* [I’m getting certs errors](https://curl-cffi.readthedocs.io/en/v0.11.2/faq.html#i-m-getting-certs-errors)
* [ErrCode: 77, Reason: error setting certificate verify locations](https://curl-cffi.readthedocs.io/en/v0.11.2/faq.html#errcode-77-reason-error-setting-certificate-verify-locations)
* [How to use with fiddler/charles to intercept content](https://curl-cffi.readthedocs.io/en/v0.11.2/faq.html#how-to-use-with-fiddler-charles-to-intercept-content)
* [ErrCode: 92, Reason: ‘HTTP/2 stream 0 was not closed cleanly: PROTOCOL\_ERROR (err 1)’](https://curl-cffi.readthedocs.io/en/v0.11.2/faq.html#errcode-92-reason-http-2-stream-0-was-not-closed-cleanly-protocol-error-err-1)
* [Packaging with PyInstaller](https://curl-cffi.readthedocs.io/en/v0.11.2/faq.html#packaging-with-pyinstaller)
* [How to set proxy?](https://curl-cffi.readthedocs.io/en/v0.11.2/faq.html#how-to-set-proxy)
* [How to change the order of headers?](https://curl-cffi.readthedocs.io/en/v0.11.2/faq.html#how-to-change-the-order-of-headers)
* [API References](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html)
* [curl low levl APIs](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl-low-levl-apis)
* [requests API](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#requests-api)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.11.2/changelog.html)
* [v0.11](https://curl-cffi.readthedocs.io/en/v0.11.2/changelog.html#v0-11)
* [v0.10](https://curl-cffi.readthedocs.io/en/v0.11.2/changelog.html#v0-10)
* [v0.9](https://curl-cffi.readthedocs.io/en/v0.11.2/changelog.html#v0-9)
* [v0.8](https://curl-cffi.readthedocs.io/en/v0.11.2/changelog.html#v0-8)
* [v0.7](https://curl-cffi.readthedocs.io/en/v0.11.2/changelog.html#v0-7)
* [v0.6](https://curl-cffi.readthedocs.io/en/v0.11.2/changelog.html#v0-6)
* [v0.5](https://curl-cffi.readthedocs.io/en/v0.11.2/changelog.html#v0-5)
* [v0.4](https://curl-cffi.readthedocs.io/en/v0.11.2/changelog.html#v0-4)
* [v0.3](https://curl-cffi.readthedocs.io/en/v0.11.2/changelog.html#v0-3)
[Discuss on Telegram](https://t.me/+lL9n33eZp480MGM1)
curl\_cffi is a Python binding for [\`curl-impersonate fork\`\_](https://curl-cffi.readthedocs.io/en/v0.11.2/#id5)
via [cffi](https://cffi.readthedocs.io/en/latest/)
. For commercial support, visit [impersonate.pro](https://impersonate.pro/)
.
Unlike other pure Python http clients like `httpx` or `requests`, `curl_cffi` can impersonate browsers’ TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try.
Sponsors[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/#sponsors "Link to this heading")
------------------------------------------------------------------------------------------
### SerpAPI[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/#serpapi "Link to this heading")
[](https://serpapi.com/)
Scrape Google and other search engines from [SerpApi](https://serpapi.com/)
’s fast, easy, and complete API. 0.66s average response time (≤ 0.5s for Ludicrous Speed Max accounts), 99.95% SLAs, pay for successful responses only.
### Bypass Cloudflare with API[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/#bypass-cloudflare-with-api "Link to this heading")
[](https://yescaptcha.com/i/stfnIO)
[Yescaptcha](https://yescaptcha.com/i/stfnIO)
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.
### Easy Captcha Bypass for Scraping[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/#easy-captcha-bypass-for-scraping "Link to this heading")
[](https://www.capsolver.com/?utm_source=github&utm_medium=banner_repo&utm_campaign=scraping&utm_term=curl_cffi)
[CapSolver](https://www.capsolver.com/?utm_source=github&utm_medium=banner_repo&utm_campaign=scraping&utm_term=curl_cffi)
is an AI-powered tool that easily bypasses Captchas, allowing uninterrupted access to public data. It supports a variety of Captchas and works seamlessly with `curl_cffi`, Puppeteer, Playwright, and more. Fast, reliable, and cost-effective. Plus, `curl_cffi` users can use the code **“CURL”** to get an extra 6% balance! and register [here](https://dashboard.capsolver.com/passport/?utm_source=github&utm_medium=banner_repo&utm_campaign=scraping&utm_term=curl_cffi)
You can also click [here](https://buymeacoffee.com/yifei)
to buy me a coffee.
* * *
Features[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/#features "Link to this heading")
------------------------------------------------------------------------------------------
* 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 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 & 3.0, which requests does not.
* Supports websocket.
| | | | | | |
| --- | --- | --- | --- | --- | --- |Feature matrix[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/#id4 "Link to this table")
| | requests | aiohttp | httpx | pycurl | curl\_cffi |
| --- | --- | --- | --- | --- | --- |
| http2 | ❌ | ❌ | ✅ | ✅ | ✅ |
| http3 | ❌ | ❌ | ❌ | ☑️ | ☑️ |
| sync | ✅ | ❌ | ✅ | ✅ | ✅ |
| async | ❌ | ✅ | ✅ | ❌ | ✅ |
| websocket | ❌ | ✅ | ❌ | ❌ | ✅ |
| fingerprints | ❌ | ❌ | ❌ | ❌ | ✅ |
| speed | 🐇 | 🐇🐇 | 🐇 | 🐇🐇 | 🐇🐇 |
Notes:
1. For pycurl, you need a http/3 enabled libcurl to make it work, while curl\_cffi packages libcurl-impersonate inside Python wheels.
2. Since v0.11.0. However, only Linux and macOS are supported, Windows is not supported due to failed building of ngtcp2.
Install[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/#install "Link to this heading")
----------------------------------------------------------------------------------------
pip install curl\_cffi \--upgrade
For more details, see [Install](https://curl-cffi.readthedocs.io/en/v0.11.2/install.html)
.
Basic Usage[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/#basic-usage "Link to this heading")
------------------------------------------------------------------------------------------------
### requests-like[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/#requests-like "Link to this heading")
import curl\_cffi
url \= "https://tls.browserleaks.com/json"
\# Notice the impersonate parameter
r \= curl\_cffi.get("https://tls.browserleaks.com/json", impersonate\="chrome110")
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")
\# http/socks proxies are supported
proxies \= {"https": "http://localhost:3128"}
r \= curl\_cffi.get("https://tls.browserleaks.com/json", impersonate\="chrome110", proxies\=proxies)
proxies \= {"https": "socks://localhost:3128"}
r \= curl\_cffi.get("https://tls.browserleaks.com/json", impersonate\="chrome110", proxies\=proxies)
### Sessions[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/#sessions "Link to this heading")
s \= curl\_cffi.Session()
\# httpbin is a http test website
s.get("https://httpbin.org/cookies/set/foo/bar")
print(s.cookies)
\# \]>
r \= s.get("https://httpbin.org/cookies")
print(r.json())
\# {'cookies': {'foo': 'bar'}}
### asyncio[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/#asyncio "Link to this heading")
async with curl\_cffi.AsyncSession() as s:
r \= await s.get("https://example.com")
More concurrency:
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)
### WebSockets[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/#websockets "Link to this heading")
from curl\_cffi import Session, WebSocket
def on\_message(ws: WebSocket, message):
print(message)
with Session() as s:
ws \= s.ws\_connect(
"wss://api.gemini.com/v1/marketdata/BTCUSD",
on\_message\=on\_message,
)
ws.run\_forever()
\# asyncio
import asyncio
from curl\_cffi import AsyncSession
async with AsyncSession() as s:
ws \= await s.ws\_connect("wss://echo.websocket.org")
await asyncio.gather(\*\[ws.send\_str("Hello, World!") for \_ in range(10)\])
async for message in ws:
print(message)
Indices and tables[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/#indices-and-tables "Link to this heading")
==============================================================================================================
* [Index](https://curl-cffi.readthedocs.io/en/v0.11.2/genindex.html)
* [Module Index](https://curl-cffi.readthedocs.io/en/v0.11.2/py-modindex.html)
* [Search Page](https://curl-cffi.readthedocs.io/en/v0.11.2/search.html)
[curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.11.2/#)
============================================================
### Navigation
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.11.2/install.html)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.11.2/impersonate.html)
* [Cookies](https://curl-cffi.readthedocs.io/en/v0.11.2/cookies.html)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.11.2/advanced.html)
* [Exceptions](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.11.2/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.11.2/faq.html)
* [API References](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.11.2/changelog.html)
### Related Topics
* [Documentation overview](https://curl-cffi.readthedocs.io/en/v0.11.2/#)
* Next: [Install](https://curl-cffi.readthedocs.io/en/v0.11.2/install.html "next chapter")
---
# Welcome to curl_cffi’s documentation! — curl_cffi documentation
Welcome to curl\_cffi’s documentation
====================================================================================================================================================
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.10.0/install.html)
* [Via pip](https://curl-cffi.readthedocs.io/en/v0.10.0/install.html#via-pip)
* [Beta versions](https://curl-cffi.readthedocs.io/en/v0.10.0/install.html#beta-versions)
* [Latest](https://curl-cffi.readthedocs.io/en/v0.10.0/install.html#latest)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.10.0/impersonate.html)
* [Supported browser versions](https://curl-cffi.readthedocs.io/en/v0.10.0/impersonate.html#supported-browser-versions)
* [Which version to use?](https://curl-cffi.readthedocs.io/en/v0.10.0/impersonate.html#which-version-to-use)
* [How to use my own fingerprints other than the builtin ones? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.10.0/impersonate.html#how-to-use-my-own-fingerprints-other-than-the-builtin-ones-e-g-okhttp)
* [Should I randomize my fingerprints for each request?](https://curl-cffi.readthedocs.io/en/v0.10.0/impersonate.html#should-i-randomize-my-fingerprints-for-each-request)
* [Can I change JavaScript fingerprints with this library?](https://curl-cffi.readthedocs.io/en/v0.10.0/impersonate.html#can-i-change-javascript-fingerprints-with-this-library)
* [Cookies](https://curl-cffi.readthedocs.io/en/v0.10.0/cookies.html)
* [How to save and load cookies](https://curl-cffi.readthedocs.io/en/v0.10.0/cookies.html#how-to-save-and-load-cookies)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.10.0/advanced.html)
* [Low-level curl API](https://curl-cffi.readthedocs.io/en/v0.10.0/advanced.html#low-level-curl-api)
* [Scrapy integrations](https://curl-cffi.readthedocs.io/en/v0.10.0/advanced.html#scrapy-integrations)
* [Using with eventlet/gevent](https://curl-cffi.readthedocs.io/en/v0.10.0/advanced.html#using-with-eventlet-gevent)
* [As a urllib3/requests adapter](https://curl-cffi.readthedocs.io/en/v0.10.0/advanced.html#as-a-urllib3-requests-adapter)
* [As a httpx transport](https://curl-cffi.readthedocs.io/en/v0.10.0/advanced.html#as-a-httpx-transport)
* [Exceptions](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html)
* [Exceptions](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#id1)
* [Warnings](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#warnings)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.10.0/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.10.0/faq.html)
* [Why does the JA3 fingerprints change for Chrome 110+ impersonation?](https://curl-cffi.readthedocs.io/en/v0.10.0/faq.html#why-does-the-ja3-fingerprints-change-for-chrome-110-impersonation)
* [Can I bypass Cloudflare with this project? or any other specific site.](https://curl-cffi.readthedocs.io/en/v0.10.0/faq.html#can-i-bypass-cloudflare-with-this-project-or-any-other-specific-site)
* [I’m getting certs errors](https://curl-cffi.readthedocs.io/en/v0.10.0/faq.html#i-m-getting-certs-errors)
* [ErrCode: 77, Reason: error setting certificate verify locations](https://curl-cffi.readthedocs.io/en/v0.10.0/faq.html#errcode-77-reason-error-setting-certificate-verify-locations)
* [How to use with fiddler/charles to intercept content](https://curl-cffi.readthedocs.io/en/v0.10.0/faq.html#how-to-use-with-fiddler-charles-to-intercept-content)
* [ErrCode: 92, Reason: ‘HTTP/2 stream 0 was not closed cleanly: PROTOCOL\_ERROR (err 1)’](https://curl-cffi.readthedocs.io/en/v0.10.0/faq.html#errcode-92-reason-http-2-stream-0-was-not-closed-cleanly-protocol-error-err-1)
* [Packaging with PyInstaller](https://curl-cffi.readthedocs.io/en/v0.10.0/faq.html#packaging-with-pyinstaller)
* [How to set proxy?](https://curl-cffi.readthedocs.io/en/v0.10.0/faq.html#how-to-set-proxy)
* [How to change the order of headers?](https://curl-cffi.readthedocs.io/en/v0.10.0/faq.html#how-to-change-the-order-of-headers)
* [API References](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html)
* [curl low levl APIs](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl-low-levl-apis)
* [requests API](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#requests-api)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.10.0/changelog.html)
* [v0.9](https://curl-cffi.readthedocs.io/en/v0.10.0/changelog.html#v0-9)
* [v0.8](https://curl-cffi.readthedocs.io/en/v0.10.0/changelog.html#v0-8)
* [v0.7](https://curl-cffi.readthedocs.io/en/v0.10.0/changelog.html#v0-7)
* [v0.6](https://curl-cffi.readthedocs.io/en/v0.10.0/changelog.html#v0-6)
* [v0.5](https://curl-cffi.readthedocs.io/en/v0.10.0/changelog.html#v0-5)
* [v0.4](https://curl-cffi.readthedocs.io/en/v0.10.0/changelog.html#v0-4)
* [v0.3](https://curl-cffi.readthedocs.io/en/v0.10.0/changelog.html#v0-3)
[Discuss on Telegram](https://t.me/+lL9n33eZp480MGM1)
curl\_cffi is a Python binding for [\`curl-impersonate fork\`\_](https://curl-cffi.readthedocs.io/en/v0.10.0/#id4)
via [cffi](https://cffi.readthedocs.io/en/latest/)
.
Unlike other pure Python http clients like `httpx` or `requests`, `curl_cffi` can impersonate browsers’ TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try.
* * *
[](https://nubela.co/proxycurl/?utm_campaign=influencer_marketing&utm_source=github&utm_medium=social&utm_term=-&utm_content=lexiforest-curl_cffi)
Scrape public LinkedIn profile data at scale with [Proxycurl APIs](https://nubela.co/proxycurl/?utm_campaign=influencer_marketing&utm_source=github&utm_medium=social&utm_term=-&utm_content=lexiforest-curl_cffi)
. Built for developers, by developers.
* GDPR, CCPA, SOC2 compliant
* High rate limit (300 requests/min), Fast (APIs respond in ~2s), High accuracy
* Fresh data - 88% of data is scraped real-time, other 12% is <29 days
* Tons of data points returned per profile
* * *
Features[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/#features "Link to this heading")
------------------------------------------------------------------------------------------
* Supports JA3/TLS and http2 fingerprints impersonation.
* Much faster than requests/httpx, on par with aiohttp/pycurl, see [benchmarks](https://github.com/lexiforest/curl_cffi/tree/main/benchmark)
.
* Mimics 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 websocket.
| | | | | | |
| --- | --- | --- | --- | --- | --- |Feature matrix[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/#id3 "Link to this table")
| | requests | aiohttp | httpx | pycurl | curl\_cffi |
| --- | --- | --- | --- | --- | --- |
| http2 | ❌ | ❌ | ✅ | ✅ | ✅ |
| sync | ✅ | ❌ | ✅ | ✅ | ✅ |
| async | ❌ | ✅ | ✅ | ❌ | ✅ |
| websocket | ❌ | ✅ | ❌ | ❌ | ✅ |
| fingerprints | ❌ | ❌ | ❌ | ❌ | ✅ |
| speed | 🐇 | 🐇🐇 | 🐇 | 🐇🐇 | 🐇🐇 |
Install[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/#install "Link to this heading")
----------------------------------------------------------------------------------------
pip install curl\_cffi \--upgrade
For more details, see [Install](https://curl-cffi.readthedocs.io/en/v0.10.0/install.html)
.
Basic Usage[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/#basic-usage "Link to this heading")
------------------------------------------------------------------------------------------------
### requests-like[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/#requests-like "Link to this heading")
import curl\_cffi
url \= "https://tools.scrapfly.io/api/fp/ja3"
\# Notice the impersonate parameter
r \= curl\_cffi.get("https://tools.scrapfly.io/api/fp/ja3", impersonate\="chrome110")
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://tools.scrapfly.io/api/fp/ja3", impersonate\="chrome")
\# http/socks proxies are supported
proxies \= {"https": "http://localhost:3128"}
r \= curl\_cffi.get("https://tools.scrapfly.io/api/fp/ja3", impersonate\="chrome110", proxies\=proxies)
proxies \= {"https": "socks://localhost:3128"}
r \= curl\_cffi.get("https://tools.scrapfly.io/api/fp/ja3", impersonate\="chrome110", proxies\=proxies)
### Sessions[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/#sessions "Link to this heading")
s \= requests.Session()
\# httpbin is a http test website
s.get("https://httpbin.org/cookies/set/foo/bar")
print(s.cookies)
\# \]>
r \= s.get("https://httpbin.org/cookies")
print(r.json())
\# {'cookies': {'foo': 'bar'}}
### asyncio[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/#asyncio "Link to this heading")
from curl\_cffi import AsyncSession
async with AsyncSession() as s:
r \= await s.get("https://example.com")
More concurrency:
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)
### WebSockets[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/#websockets "Link to this heading")
from curl\_cffi import Session, WebSocket
def on\_message(ws: WebSocket, message):
print(message)
with Session() as s:
ws \= s.ws\_connect(
"wss://api.gemini.com/v1/marketdata/BTCUSD",
on\_message\=on\_message,
)
ws.run\_forever()
Sponsor[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/#sponsor "Link to this heading")
----------------------------------------------------------------------------------------
Click [here](https://buymeacoffee.com/yifei)
to buy me a coffee.
### Bypass Cloudflare with API[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/#bypass-cloudflare-with-api "Link to this heading")
[](https://yescaptcha.com/i/stfnIO)
[Yescaptcha](https://yescaptcha.com/i/stfnIO)
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.
### ScrapeNinja[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/#scrapeninja "Link to this heading")
[](https://scrapeninja.net/?utm_source=github&utm_medium=banner&utm_campaign=cffi)
[ScrapeNinja](https://scrapeninja.net/?utm_source=github&utm_medium=banner&utm_campaign=cffi)
is a web scraping API with two engines: fast, with high performance and TLS fingerprint; and slower with a real browser under the hood.
ScrapeNinja handles headless browsers, proxies, timeouts, retries, and helps with data extraction, so you can just get the data in JSON. Rotating proxies are available out of the box on all subscription plans.
Indices and tables[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/#indices-and-tables "Link to this heading")
==============================================================================================================
* [Index](https://curl-cffi.readthedocs.io/en/v0.10.0/genindex.html)
* [Module Index](https://curl-cffi.readthedocs.io/en/v0.10.0/py-modindex.html)
* [Search Page](https://curl-cffi.readthedocs.io/en/v0.10.0/search.html)
[curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.10.0/#)
============================================================
### Navigation
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.10.0/install.html)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.10.0/impersonate.html)
* [Cookies](https://curl-cffi.readthedocs.io/en/v0.10.0/cookies.html)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.10.0/advanced.html)
* [Exceptions](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.10.0/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.10.0/faq.html)
* [API References](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.10.0/changelog.html)
### Related Topics
* [Documentation overview](https://curl-cffi.readthedocs.io/en/v0.10.0/#)
* Next: [Install](https://curl-cffi.readthedocs.io/en/v0.10.0/install.html "next chapter")
---
# Welcome to curl_cffi’s documentation! — curl_cffi documentation
Welcome to curl\_cffi’s documentation
====================================================================================================================================================
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.11.1/install.html)
* [Via pip](https://curl-cffi.readthedocs.io/en/v0.11.1/install.html#via-pip)
* [Beta versions](https://curl-cffi.readthedocs.io/en/v0.11.1/install.html#beta-versions)
* [Latest](https://curl-cffi.readthedocs.io/en/v0.11.1/install.html#latest)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.11.1/impersonate.html)
* [Supported browser versions](https://curl-cffi.readthedocs.io/en/v0.11.1/impersonate.html#supported-browser-versions)
* [Which version to use?](https://curl-cffi.readthedocs.io/en/v0.11.1/impersonate.html#which-version-to-use)
* [How to use my own fingerprints other than the builtin ones? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.11.1/impersonate.html#how-to-use-my-own-fingerprints-other-than-the-builtin-ones-e-g-okhttp)
* [Should I randomize my fingerprints for each request?](https://curl-cffi.readthedocs.io/en/v0.11.1/impersonate.html#should-i-randomize-my-fingerprints-for-each-request)
* [Can I change JavaScript fingerprints with this library?](https://curl-cffi.readthedocs.io/en/v0.11.1/impersonate.html#can-i-change-javascript-fingerprints-with-this-library)
* [Cookies](https://curl-cffi.readthedocs.io/en/v0.11.1/cookies.html)
* [How to save and load cookies](https://curl-cffi.readthedocs.io/en/v0.11.1/cookies.html#how-to-save-and-load-cookies)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.11.1/advanced.html)
* [Low-level curl API](https://curl-cffi.readthedocs.io/en/v0.11.1/advanced.html#low-level-curl-api)
* [Scrapy integrations](https://curl-cffi.readthedocs.io/en/v0.11.1/advanced.html#scrapy-integrations)
* [Using with eventlet/gevent](https://curl-cffi.readthedocs.io/en/v0.11.1/advanced.html#using-with-eventlet-gevent)
* [As a urllib3/requests adapter](https://curl-cffi.readthedocs.io/en/v0.11.1/advanced.html#as-a-urllib3-requests-adapter)
* [As a httpx transport](https://curl-cffi.readthedocs.io/en/v0.11.1/advanced.html#as-a-httpx-transport)
* [Keeping session alive in http/2](https://curl-cffi.readthedocs.io/en/v0.11.1/advanced.html#keeping-session-alive-in-http-2)
* [Exceptions](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html)
* [Exceptions](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#id1)
* [Warnings](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#warnings)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.11.1/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.11.1/faq.html)
* [Why does the JA3 fingerprints change for Chrome 110+ impersonation?](https://curl-cffi.readthedocs.io/en/v0.11.1/faq.html#why-does-the-ja3-fingerprints-change-for-chrome-110-impersonation)
* [Can I bypass Cloudflare with this project? or any other specific site.](https://curl-cffi.readthedocs.io/en/v0.11.1/faq.html#can-i-bypass-cloudflare-with-this-project-or-any-other-specific-site)
* [I’m getting certs errors](https://curl-cffi.readthedocs.io/en/v0.11.1/faq.html#i-m-getting-certs-errors)
* [ErrCode: 77, Reason: error setting certificate verify locations](https://curl-cffi.readthedocs.io/en/v0.11.1/faq.html#errcode-77-reason-error-setting-certificate-verify-locations)
* [How to use with fiddler/charles to intercept content](https://curl-cffi.readthedocs.io/en/v0.11.1/faq.html#how-to-use-with-fiddler-charles-to-intercept-content)
* [ErrCode: 92, Reason: ‘HTTP/2 stream 0 was not closed cleanly: PROTOCOL\_ERROR (err 1)’](https://curl-cffi.readthedocs.io/en/v0.11.1/faq.html#errcode-92-reason-http-2-stream-0-was-not-closed-cleanly-protocol-error-err-1)
* [Packaging with PyInstaller](https://curl-cffi.readthedocs.io/en/v0.11.1/faq.html#packaging-with-pyinstaller)
* [How to set proxy?](https://curl-cffi.readthedocs.io/en/v0.11.1/faq.html#how-to-set-proxy)
* [How to change the order of headers?](https://curl-cffi.readthedocs.io/en/v0.11.1/faq.html#how-to-change-the-order-of-headers)
* [API References](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html)
* [curl low levl APIs](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl-low-levl-apis)
* [requests API](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#requests-api)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.11.1/changelog.html)
* [v0.11](https://curl-cffi.readthedocs.io/en/v0.11.1/changelog.html#v0-11)
* [v0.10](https://curl-cffi.readthedocs.io/en/v0.11.1/changelog.html#v0-10)
* [v0.9](https://curl-cffi.readthedocs.io/en/v0.11.1/changelog.html#v0-9)
* [v0.8](https://curl-cffi.readthedocs.io/en/v0.11.1/changelog.html#v0-8)
* [v0.7](https://curl-cffi.readthedocs.io/en/v0.11.1/changelog.html#v0-7)
* [v0.6](https://curl-cffi.readthedocs.io/en/v0.11.1/changelog.html#v0-6)
* [v0.5](https://curl-cffi.readthedocs.io/en/v0.11.1/changelog.html#v0-5)
* [v0.4](https://curl-cffi.readthedocs.io/en/v0.11.1/changelog.html#v0-4)
* [v0.3](https://curl-cffi.readthedocs.io/en/v0.11.1/changelog.html#v0-3)
[Discuss on Telegram](https://t.me/+lL9n33eZp480MGM1)
curl\_cffi is a Python binding for [\`curl-impersonate fork\`\_](https://curl-cffi.readthedocs.io/en/v0.11.1/#id5)
via [cffi](https://cffi.readthedocs.io/en/latest/)
. For commercial support, visit [impersonate.pro](https://impersonate.pro/)
.
Unlike other pure Python http clients like `httpx` or `requests`, `curl_cffi` can impersonate browsers’ TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try.
Sponsors[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/#sponsors "Link to this heading")
------------------------------------------------------------------------------------------
### SerpAPI[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/#serpapi "Link to this heading")
[](https://serpapi.com/)
Scrape Google and other search engines from [SerpApi](https://serpapi.com/)
’s fast, easy, and complete API. 0.66s average response time (≤ 0.5s for Ludicrous Speed Max accounts), 99.95% SLAs, pay for successful responses only.
### Bypass Cloudflare with API[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/#bypass-cloudflare-with-api "Link to this heading")
[](https://yescaptcha.com/i/stfnIO)
[Yescaptcha](https://yescaptcha.com/i/stfnIO)
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.
### Easy Captcha Bypass for Scraping[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/#easy-captcha-bypass-for-scraping "Link to this heading")
[](https://www.capsolver.com/?utm_source=github&utm_medium=banner_repo&utm_campaign=scraping&utm_term=curl_cffi)
[CapSolver](https://www.capsolver.com/?utm_source=github&utm_medium=banner_repo&utm_campaign=scraping&utm_term=curl_cffi)
is an AI-powered tool that easily bypasses Captchas, allowing uninterrupted access to public data. It supports a variety of Captchas and works seamlessly with `curl_cffi`, Puppeteer, Playwright, and more. Fast, reliable, and cost-effective. Plus, `curl_cffi` users can use the code **“CURL”** to get an extra 6% balance! and register [here](https://dashboard.capsolver.com/passport/?utm_source=github&utm_medium=banner_repo&utm_campaign=scraping&utm_term=curl_cffi)
You can also click [here](https://buymeacoffee.com/yifei)
to buy me a coffee.
* * *
Features[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/#features "Link to this heading")
------------------------------------------------------------------------------------------
* 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 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 & 3.0, which requests does not.
* Supports websocket.
| | | | | | |
| --- | --- | --- | --- | --- | --- |Feature matrix[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/#id4 "Link to this table")
| | requests | aiohttp | httpx | pycurl | curl\_cffi |
| --- | --- | --- | --- | --- | --- |
| http2 | ❌ | ❌ | ✅ | ✅ | ✅ |
| http3 | ❌ | ❌ | ❌ | ☑️ | ☑️ |
| sync | ✅ | ❌ | ✅ | ✅ | ✅ |
| async | ❌ | ✅ | ✅ | ❌ | ✅ |
| websocket | ❌ | ✅ | ❌ | ❌ | ✅ |
| fingerprints | ❌ | ❌ | ❌ | ❌ | ✅ |
| speed | 🐇 | 🐇🐇 | 🐇 | 🐇🐇 | 🐇🐇 |
Notes:
1. For pycurl, you need a http/3 enabled libcurl to make it work, while curl\_cffi packages libcurl-impersonate inside Python wheels.
2. Since v0.11.0. However, only Linux and macOS are supported, Windows is not supported due to failed building of ngtcp2.
Install[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/#install "Link to this heading")
----------------------------------------------------------------------------------------
pip install curl\_cffi \--upgrade
For more details, see [Install](https://curl-cffi.readthedocs.io/en/v0.11.1/install.html)
.
Basic Usage[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/#basic-usage "Link to this heading")
------------------------------------------------------------------------------------------------
### requests-like[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/#requests-like "Link to this heading")
import curl\_cffi
url \= "https://tls.browserleaks.com/json"
\# Notice the impersonate parameter
r \= curl\_cffi.get("https://tls.browserleaks.com/json", impersonate\="chrome110")
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")
\# http/socks proxies are supported
proxies \= {"https": "http://localhost:3128"}
r \= curl\_cffi.get("https://tls.browserleaks.com/json", impersonate\="chrome110", proxies\=proxies)
proxies \= {"https": "socks://localhost:3128"}
r \= curl\_cffi.get("https://tls.browserleaks.com/json", impersonate\="chrome110", proxies\=proxies)
### Sessions[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/#sessions "Link to this heading")
s \= curl\_cffi.Session()
\# httpbin is a http test website
s.get("https://httpbin.org/cookies/set/foo/bar")
print(s.cookies)
\# \]>
r \= s.get("https://httpbin.org/cookies")
print(r.json())
\# {'cookies': {'foo': 'bar'}}
### asyncio[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/#asyncio "Link to this heading")
async with curl\_cffi.AsyncSession() as s:
r \= await s.get("https://example.com")
More concurrency:
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)
### WebSockets[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/#websockets "Link to this heading")
from curl\_cffi import Session, WebSocket
def on\_message(ws: WebSocket, message):
print(message)
with Session() as s:
ws \= s.ws\_connect(
"wss://api.gemini.com/v1/marketdata/BTCUSD",
on\_message\=on\_message,
)
ws.run\_forever()
\# asyncio
import asyncio
from curl\_cffi import AsyncSession
async with AsyncSession() as s:
ws \= await s.ws\_connect("wss://echo.websocket.org")
await asyncio.gather(\*\[ws.send\_str("Hello, World!") for \_ in range(10)\])
async for message in ws:
print(message)
Indices and tables[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/#indices-and-tables "Link to this heading")
==============================================================================================================
* [Index](https://curl-cffi.readthedocs.io/en/v0.11.1/genindex.html)
* [Module Index](https://curl-cffi.readthedocs.io/en/v0.11.1/py-modindex.html)
* [Search Page](https://curl-cffi.readthedocs.io/en/v0.11.1/search.html)
[curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.11.1/#)
============================================================
### Navigation
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.11.1/install.html)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.11.1/impersonate.html)
* [Cookies](https://curl-cffi.readthedocs.io/en/v0.11.1/cookies.html)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.11.1/advanced.html)
* [Exceptions](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.11.1/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.11.1/faq.html)
* [API References](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.11.1/changelog.html)
### Related Topics
* [Documentation overview](https://curl-cffi.readthedocs.io/en/v0.11.1/#)
* Next: [Install](https://curl-cffi.readthedocs.io/en/v0.11.1/install.html "next chapter")
---
# curl_cffi’s documentation — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html "Quick Start")
|
* [Top](https://curl-cffi.readthedocs.io/en/v0.11.3/#)
»
* [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/v0.11.3/)
curl\_cffi’s documentation[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/#curl-cffi-s-documentation "Link to this heading")
=============================================================================================================================
Contents:
* [Quick Start](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html)
* [Install](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#install)
* [requests-like](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#requests-like)
* [Asyncio](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#asyncio)
* [WebSockets](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#websockets)
* [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.html)
* [What is TLS and http/2, http/3 fingerprinting?](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.html#what-is-tls-and-http-2-http-3-fingerprinting)
* [Supported browser impersonate targets](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.html#supported-browser-impersonate-targets)
* [Which target version to use?](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.html#which-target-version-to-use)
* [How to use my own fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.html#how-to-use-my-own-fingerprints-e-g-okhttp)
* [How to check if my impersonation is working?](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.html#how-to-check-if-my-impersonation-is-working)
* [I’m still being detected even if I impersonated correctly](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.html#i-m-still-being-detected-even-if-i-impersonated-correctly)
* [Should I randomize my fingerprints for each request?](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.html#should-i-randomize-my-fingerprints-for-each-request)
* [Can I change JavaScript fingerprints with this library?](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.html#can-i-change-javascript-fingerprints-with-this-library)
* [Advanced Topics](https://curl-cffi.readthedocs.io/en/v0.11.3/advanced.html)
* [Proxies](https://curl-cffi.readthedocs.io/en/v0.11.3/advanced.html#proxies)
* [Low-level curl API](https://curl-cffi.readthedocs.io/en/v0.11.3/advanced.html#low-level-curl-api)
* [Using `CURLOPT_*` in requests API](https://curl-cffi.readthedocs.io/en/v0.11.3/advanced.html#using-curlopt-in-requests-api)
* [Selecting http version](https://curl-cffi.readthedocs.io/en/v0.11.3/advanced.html#selecting-http-version)
* [Keeping session alive in http/2](https://curl-cffi.readthedocs.io/en/v0.11.3/advanced.html#keeping-session-alive-in-http-2)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.11.3/vs-requests.html)
* [Transports and Adapters](https://curl-cffi.readthedocs.io/en/v0.11.3/vs-requests.html#transports-and-adapters)
* [Cookies](https://curl-cffi.readthedocs.io/en/v0.11.3/cookies.html)
* [Save and load cookies](https://curl-cffi.readthedocs.io/en/v0.11.3/cookies.html#save-and-load-cookies)
* [Discard cookies when using Session](https://curl-cffi.readthedocs.io/en/v0.11.3/cookies.html#discard-cookies-when-using-session)
* [Community](https://curl-cffi.readthedocs.io/en/v0.11.3/community.html)
* [Scrapy integrations](https://curl-cffi.readthedocs.io/en/v0.11.3/community.html#scrapy-integrations)
* [Using with eventlet/gevent](https://curl-cffi.readthedocs.io/en/v0.11.3/community.html#using-with-eventlet-gevent)
* [As a urllib3/requests adapter](https://curl-cffi.readthedocs.io/en/v0.11.3/community.html#as-a-urllib3-requests-adapter)
* [As a httpx transport](https://curl-cffi.readthedocs.io/en/v0.11.3/community.html#as-a-httpx-transport)
* [API References](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html)
* [curl low levl APIs](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl-low-levl-apis)
* [requests-like API](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#requests-like-api)
* [Asyncio](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#asyncio)
* [WebSocket](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#websocket)
* [Exceptions and Warnings](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#exceptions-and-warnings)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.11.3/faq.html)
* [What does the pro version offer? Is the open source project still maintained?](https://curl-cffi.readthedocs.io/en/v0.11.3/faq.html#what-does-the-pro-version-offer-is-the-open-source-project-still-maintained)
* [Why does the JA3 fingerprints change for Chrome 110+ impersonation?](https://curl-cffi.readthedocs.io/en/v0.11.3/faq.html#why-does-the-ja3-fingerprints-change-for-chrome-110-impersonation)
* [Can I bypass Cloudflare with this project? or any other specific site.](https://curl-cffi.readthedocs.io/en/v0.11.3/faq.html#can-i-bypass-cloudflare-with-this-project-or-any-other-specific-site)
* [I’m getting certs errors](https://curl-cffi.readthedocs.io/en/v0.11.3/faq.html#i-m-getting-certs-errors)
* [ErrCode: 77, Reason: error setting certificate verify locations](https://curl-cffi.readthedocs.io/en/v0.11.3/faq.html#errcode-77-reason-error-setting-certificate-verify-locations)
* [How to use with fiddler/charles to intercept content](https://curl-cffi.readthedocs.io/en/v0.11.3/faq.html#how-to-use-with-fiddler-charles-to-intercept-content)
* [ErrCode: 92, Reason: ‘HTTP/2 stream 0 was not closed cleanly: PROTOCOL\_ERROR (err 1)’](https://curl-cffi.readthedocs.io/en/v0.11.3/faq.html#errcode-92-reason-http-2-stream-0-was-not-closed-cleanly-protocol-error-err-1)
* [Packaging with PyInstaller](https://curl-cffi.readthedocs.io/en/v0.11.3/faq.html#packaging-with-pyinstaller)
* [How to change the order of headers?](https://curl-cffi.readthedocs.io/en/v0.11.3/faq.html#how-to-change-the-order-of-headers)
* [How to deal with encoding/decoding errors?](https://curl-cffi.readthedocs.io/en/v0.11.3/faq.html#how-to-deal-with-encoding-decoding-errors)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.11.3/changelog.html)
* [Development and contributing](https://curl-cffi.readthedocs.io/en/v0.11.3/dev.html)
* [Contributing](https://curl-cffi.readthedocs.io/en/v0.11.3/dev.html#contributing)
[Discuss on Telegram](https://t.me/+lL9n33eZp480MGM1)
curl\_cffi is a 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/)
.
Unlike other pure Python http clients like `httpx` or `requests`, `curl_cffi` can impersonate browsers’ TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try.
If you are looking for Python http3 clients, curl\_cffi added http3 support since `v0.11`.
Sponsors[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/#sponsors "Link to this heading")
------------------------------------------------------------------------------------------
### SerpAPI[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/#serpapi "Link to this heading")
[](https://serpapi.com/)
Scrape Google and other search engines from [SerpApi](https://serpapi.com/)
’s fast, easy, and complete API. 0.66s average response time (≤ 0.5s for Ludicrous Speed Max accounts), 99.95% SLAs, pay for successful responses only.
### Bypass Cloudflare with API[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/#bypass-cloudflare-with-api "Link to this heading")
[](https://yescaptcha.com/i/stfnIO)
[Yescaptcha](https://yescaptcha.com/i/stfnIO)
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.
### Easy Captcha Bypass for Scraping[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/#easy-captcha-bypass-for-scraping "Link to this heading")
[](https://www.capsolver.com/?utm_source=github&utm_medium=banner_repo&utm_campaign=scraping&utm_term=curl_cffi)
[CapSolver](https://www.capsolver.com/?utm_source=github&utm_medium=banner_repo&utm_campaign=scraping&utm_term=curl_cffi)
is an AI-powered tool that easily bypasses Captchas, allowing uninterrupted access to public data. It supports a variety of Captchas and works seamlessly with `curl_cffi`, Puppeteer, Playwright, and more. Fast, reliable, and cost-effective. Plus, `curl_cffi` users can use the code **“CURL”** to get an extra 6% balance! and register [here](https://dashboard.capsolver.com/passport/?utm_source=github&utm_medium=banner_repo&utm_campaign=scraping&utm_term=curl_cffi)
You can also click [here](https://buymeacoffee.com/yifei)
to buy me a coffee.
Features[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/#features "Link to this heading")
------------------------------------------------------------------------------------------
* 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 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 & 3.0, which requests does not.
* Supports websocket.
| | | | | | |
| --- | --- | --- | --- | --- | --- |Feature matrix[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/#id4 "Link to this table")
| | requests | aiohttp | httpx | pycurl | curl\_cffi |
| --- | --- | --- | --- | --- | --- |
| http2 | ❌ | ❌ | ✅ | ✅ | ✅ |
| http3 | ❌ | ❌ | ❌ | ☑️ | ☑️ |
| sync | ✅ | ❌ | ✅ | ✅ | ✅ |
| async | ❌ | ✅ | ✅ | ❌ | ✅ |
| websocket | ❌ | ✅ | ❌ | ❌ | ✅ |
| fingerprints | ❌ | ❌ | ❌ | ❌ | ✅ |
| speed | 🐇 | 🐇🐇 | 🐇 | 🐇🐇 | 🐇🐇 |
Notes:
1. For pycurl, you need a http/3 enabled libcurl to make it work, while curl\_cffi packages libcurl-impersonate inside Python wheels.
2. Since v0.11.0. However, only Linux and macOS are supported, Windows is not supported due to failed building of ngtcp2.
Install[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/#install "Link to this heading")
----------------------------------------------------------------------------------------
pip install curl\_cffi \--upgrade
For more details, see install.
Documentation[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/#documentation "Link to this heading")
----------------------------------------------------------------------------------------------------
You can first check out [Quick Start](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html)
. Then the [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.html)
.
For advanced topics, checkout [Cookies](https://curl-cffi.readthedocs.io/en/v0.11.3/cookies.html)
, [Asyncio](https://curl-cffi.readthedocs.io/en/v0.11.3/asyncio.html)
and [WebSockets](https://curl-cffi.readthedocs.io/en/v0.11.3/websockets.html)
.
You can also find common use cases in the [examples](https://github.com/lexiforest/curl_cffi/tree/main/examples)
directory.
Finally, if something is missing from the tutorial, you can always find them in the [API References](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html)
.
If you have any questions, be sure to check out the [FAQ](https://curl-cffi.readthedocs.io/en/v0.11.3/faq.html)
section before opening an issue.
Indices and tables[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/#indices-and-tables "Link to this heading")
==============================================================================================================
* [Index](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html)
* [Module Index](https://curl-cffi.readthedocs.io/en/v0.11.3/py-modindex.html)
* [Search Page](https://curl-cffi.readthedocs.io/en/v0.11.3/search.html)
### [Table of Contents](https://curl-cffi.readthedocs.io/en/v0.11.3/#)
* [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/v0.11.3/#)
* [Sponsors](https://curl-cffi.readthedocs.io/en/v0.11.3/#sponsors)
* [SerpAPI](https://curl-cffi.readthedocs.io/en/v0.11.3/#serpapi)
* [Bypass Cloudflare with API](https://curl-cffi.readthedocs.io/en/v0.11.3/#bypass-cloudflare-with-api)
* [Easy Captcha Bypass for Scraping](https://curl-cffi.readthedocs.io/en/v0.11.3/#easy-captcha-bypass-for-scraping)
* [Features](https://curl-cffi.readthedocs.io/en/v0.11.3/#features)
* [Install](https://curl-cffi.readthedocs.io/en/v0.11.3/#install)
* [Documentation](https://curl-cffi.readthedocs.io/en/v0.11.3/#documentation)
* [Indices and tables](https://curl-cffi.readthedocs.io/en/v0.11.3/#indices-and-tables)
#### Next topic
[Quick Start](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html "next chapter")
### This Page
* [Show Source](https://curl-cffi.readthedocs.io/en/v0.11.3/_sources/index.rst.txt)
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html "Quick Start")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.3/#)
»
* [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/v0.11.3/)
---
# curl_cffi’s documentation — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html "Quick Start")
|
* [Top](https://curl-cffi.readthedocs.io/en/v0.11.4/#)
»
* [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/v0.11.4/)
curl\_cffi’s documentation[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/#curl-cffi-s-documentation "Link to this heading")
=============================================================================================================================
Contents:
* [Quick Start](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html)
* [Install](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#install)
* [requests-like](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#requests-like)
* [Asyncio](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#asyncio)
* [WebSockets](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#websockets)
* [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.html)
* [What is TLS and http/2, http/3 fingerprinting?](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.html#what-is-tls-and-http-2-http-3-fingerprinting)
* [Supported browser impersonate targets](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.html#supported-browser-impersonate-targets)
* [Which target version to use?](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.html#which-target-version-to-use)
* [How to use my own fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.html#how-to-use-my-own-fingerprints-e-g-okhttp)
* [How to check if my impersonation is working?](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.html#how-to-check-if-my-impersonation-is-working)
* [I’m still being detected even if I impersonated correctly](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.html#i-m-still-being-detected-even-if-i-impersonated-correctly)
* [Should I randomize my fingerprints for each request?](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.html#should-i-randomize-my-fingerprints-for-each-request)
* [Can I change JavaScript fingerprints with this library?](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.html#can-i-change-javascript-fingerprints-with-this-library)
* [Why are all the User-Agents macOS?](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.html#why-are-all-the-user-agents-macos)
* [Advanced Topics](https://curl-cffi.readthedocs.io/en/v0.11.4/advanced.html)
* [Proxies](https://curl-cffi.readthedocs.io/en/v0.11.4/advanced.html#proxies)
* [Low-level curl API](https://curl-cffi.readthedocs.io/en/v0.11.4/advanced.html#low-level-curl-api)
* [Using `CURLOPT_*` in requests API](https://curl-cffi.readthedocs.io/en/v0.11.4/advanced.html#using-curlopt-in-requests-api)
* [Selecting http version](https://curl-cffi.readthedocs.io/en/v0.11.4/advanced.html#selecting-http-version)
* [Keeping session alive in http/2](https://curl-cffi.readthedocs.io/en/v0.11.4/advanced.html#keeping-session-alive-in-http-2)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.11.4/vs-requests.html)
* [Transports and Adapters](https://curl-cffi.readthedocs.io/en/v0.11.4/vs-requests.html#transports-and-adapters)
* [Cookies](https://curl-cffi.readthedocs.io/en/v0.11.4/cookies.html)
* [Save and load cookies](https://curl-cffi.readthedocs.io/en/v0.11.4/cookies.html#save-and-load-cookies)
* [Discard cookies when using Session](https://curl-cffi.readthedocs.io/en/v0.11.4/cookies.html#discard-cookies-when-using-session)
* [Community](https://curl-cffi.readthedocs.io/en/v0.11.4/community.html)
* [Scrapy integrations](https://curl-cffi.readthedocs.io/en/v0.11.4/community.html#scrapy-integrations)
* [Using with eventlet/gevent](https://curl-cffi.readthedocs.io/en/v0.11.4/community.html#using-with-eventlet-gevent)
* [As a urllib3/requests adapter](https://curl-cffi.readthedocs.io/en/v0.11.4/community.html#as-a-urllib3-requests-adapter)
* [As a httpx transport](https://curl-cffi.readthedocs.io/en/v0.11.4/community.html#as-a-httpx-transport)
* [API References](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html)
* [curl low levl APIs](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl-low-levl-apis)
* [requests-like API](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#requests-like-api)
* [Asyncio](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#asyncio)
* [WebSocket](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#websocket)
* [Exceptions and Warnings](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#exceptions-and-warnings)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.11.4/faq.html)
* [What does the pro version offer? Is the open source project still maintained?](https://curl-cffi.readthedocs.io/en/v0.11.4/faq.html#what-does-the-pro-version-offer-is-the-open-source-project-still-maintained)
* [Why does the JA3 fingerprints change for Chrome 110+ impersonation?](https://curl-cffi.readthedocs.io/en/v0.11.4/faq.html#why-does-the-ja3-fingerprints-change-for-chrome-110-impersonation)
* [Can I bypass Cloudflare with this project? or any other specific site.](https://curl-cffi.readthedocs.io/en/v0.11.4/faq.html#can-i-bypass-cloudflare-with-this-project-or-any-other-specific-site)
* [I’m getting certs errors](https://curl-cffi.readthedocs.io/en/v0.11.4/faq.html#i-m-getting-certs-errors)
* [ErrCode: 77, Reason: error setting certificate verify locations](https://curl-cffi.readthedocs.io/en/v0.11.4/faq.html#errcode-77-reason-error-setting-certificate-verify-locations)
* [How to use with fiddler/charles to intercept content](https://curl-cffi.readthedocs.io/en/v0.11.4/faq.html#how-to-use-with-fiddler-charles-to-intercept-content)
* [ErrCode: 92, Reason: ‘HTTP/2 stream 0 was not closed cleanly: PROTOCOL\_ERROR (err 1)’](https://curl-cffi.readthedocs.io/en/v0.11.4/faq.html#errcode-92-reason-http-2-stream-0-was-not-closed-cleanly-protocol-error-err-1)
* [Packaging with PyInstaller](https://curl-cffi.readthedocs.io/en/v0.11.4/faq.html#packaging-with-pyinstaller)
* [How to change the order of headers?](https://curl-cffi.readthedocs.io/en/v0.11.4/faq.html#how-to-change-the-order-of-headers)
* [How to deal with encoding/decoding errors?](https://curl-cffi.readthedocs.io/en/v0.11.4/faq.html#how-to-deal-with-encoding-decoding-errors)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.11.4/changelog.html)
* [Development and contributing](https://curl-cffi.readthedocs.io/en/v0.11.4/dev.html)
* [Contributing](https://curl-cffi.readthedocs.io/en/v0.11.4/dev.html#contributing)
[Discuss on Telegram](https://t.me/+lL9n33eZp480MGM1)
curl\_cffi is a 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/)
.
Unlike other pure Python http clients like `httpx` or `requests`, `curl_cffi` can impersonate browsers’ TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try.
If you are looking for Python http3 clients, curl\_cffi added http3 support since `v0.11`.
Sponsors[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/#sponsors "Link to this heading")
------------------------------------------------------------------------------------------
### SerpAPI[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/#serpapi "Link to this heading")
[](https://serpapi.com/)
Scrape Google and other search engines from [SerpApi](https://serpapi.com/)
’s fast, easy, and complete API. 0.66s average response time (≤ 0.5s for Ludicrous Speed Max accounts), 99.95% SLAs, pay for successful responses only.
### Bypass Cloudflare with API[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/#bypass-cloudflare-with-api "Link to this heading")
[](https://yescaptcha.com/i/stfnIO)
[Yescaptcha](https://yescaptcha.com/i/stfnIO)
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.
### Easy Captcha Bypass for Scraping[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/#easy-captcha-bypass-for-scraping "Link to this heading")
[](https://www.capsolver.com/?utm_source=github&utm_medium=banner_repo&utm_campaign=scraping&utm_term=curl_cffi)
[CapSolver](https://www.capsolver.com/?utm_source=github&utm_medium=banner_repo&utm_campaign=scraping&utm_term=curl_cffi)
is an AI-powered tool that easily bypasses Captchas, allowing uninterrupted access to public data. It supports a variety of Captchas and works seamlessly with `curl_cffi`, Puppeteer, Playwright, and more. Fast, reliable, and cost-effective. Plus, `curl_cffi` users can use the code **“CURL”** to get an extra 6% balance! and register [here](https://dashboard.capsolver.com/passport/?utm_source=github&utm_medium=banner_repo&utm_campaign=scraping&utm_term=curl_cffi)
You can also click [here](https://buymeacoffee.com/yifei)
to buy me a coffee.
Features[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/#features "Link to this heading")
------------------------------------------------------------------------------------------
* 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 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 & 3.0, which requests does not.
* Supports websocket.
| | | | | | |
| --- | --- | --- | --- | --- | --- |Feature matrix[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/#id4 "Link to this table")
| | requests | aiohttp | httpx | pycurl | curl\_cffi |
| --- | --- | --- | --- | --- | --- |
| http2 | ❌ | ❌ | ✅ | ✅ | ✅ |
| http3 | ❌ | ❌ | ❌ | ☑️ | ☑️ |
| sync | ✅ | ❌ | ✅ | ✅ | ✅ |
| async | ❌ | ✅ | ✅ | ❌ | ✅ |
| websocket | ❌ | ✅ | ❌ | ❌ | ✅ |
| fingerprints | ❌ | ❌ | ❌ | ❌ | ✅ |
| speed | 🐇 | 🐇🐇 | 🐇 | 🐇🐇 | 🐇🐇 |
Notes:
1. For pycurl, you need a http/3 enabled libcurl to make it work, while curl\_cffi packages libcurl-impersonate inside Python wheels.
2. Since v0.11.0. However, only Linux and macOS are supported, Windows is not supported due to failed building of ngtcp2.
Install[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/#install "Link to this heading")
----------------------------------------------------------------------------------------
pip install curl\_cffi \--upgrade
For more details, see install.
Documentation[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/#documentation "Link to this heading")
----------------------------------------------------------------------------------------------------
You can first check out [Quick Start](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html)
. Then the [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.html)
.
For advanced topics, checkout [Cookies](https://curl-cffi.readthedocs.io/en/v0.11.4/cookies.html)
, [Asyncio](https://curl-cffi.readthedocs.io/en/v0.11.4/asyncio.html)
and [WebSockets](https://curl-cffi.readthedocs.io/en/v0.11.4/websockets.html)
.
You can also find common use cases in the [examples](https://github.com/lexiforest/curl_cffi/tree/main/examples)
directory.
Finally, if something is missing from the tutorial, you can always find them in the [API References](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html)
.
If you have any questions, be sure to check out the [FAQ](https://curl-cffi.readthedocs.io/en/v0.11.4/faq.html)
section before opening an issue.
Indices and tables[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/#indices-and-tables "Link to this heading")
==============================================================================================================
* [Index](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html)
* [Module Index](https://curl-cffi.readthedocs.io/en/v0.11.4/py-modindex.html)
* [Search Page](https://curl-cffi.readthedocs.io/en/v0.11.4/search.html)
### [Table of Contents](https://curl-cffi.readthedocs.io/en/v0.11.4/#)
* [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/v0.11.4/#)
* [Sponsors](https://curl-cffi.readthedocs.io/en/v0.11.4/#sponsors)
* [SerpAPI](https://curl-cffi.readthedocs.io/en/v0.11.4/#serpapi)
* [Bypass Cloudflare with API](https://curl-cffi.readthedocs.io/en/v0.11.4/#bypass-cloudflare-with-api)
* [Easy Captcha Bypass for Scraping](https://curl-cffi.readthedocs.io/en/v0.11.4/#easy-captcha-bypass-for-scraping)
* [Features](https://curl-cffi.readthedocs.io/en/v0.11.4/#features)
* [Install](https://curl-cffi.readthedocs.io/en/v0.11.4/#install)
* [Documentation](https://curl-cffi.readthedocs.io/en/v0.11.4/#documentation)
* [Indices and tables](https://curl-cffi.readthedocs.io/en/v0.11.4/#indices-and-tables)
#### Next topic
[Quick Start](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html "next chapter")
### This Page
* [Show Source](https://curl-cffi.readthedocs.io/en/v0.11.4/_sources/index.rst.txt)
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html "Quick Start")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.4/#)
»
* [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/v0.11.4/)
---
# curl_cffi’s documentation — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html "Quick Start")
|
* [Top](https://curl-cffi.readthedocs.io/en/v0.13.0/#)
»
* [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/v0.13.0/)
curl\_cffi’s documentation[¶](https://curl-cffi.readthedocs.io/en/v0.13.0/#curl-cffi-s-documentation "Link to this heading")
=============================================================================================================================
Contents:
* [Quick Start](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html)
* [Install](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#install)
* [requests-like](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#requests-like)
* [Asyncio](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#asyncio)
* [WebSockets](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#websockets)
* [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/_index.html)
* [What is TLS and http/2, http/3 fingerprinting?](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/fingerprint.html)
* [Supported browser impersonate targets](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/targets.html)
* [Which target version to use?](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/targets.html#which-target-version-to-use)
* [How to use my own fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/customize.html)
* [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/psk.html)
* [Impersonation FAQ](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/faq.html)
* [Advanced Topics](https://curl-cffi.readthedocs.io/en/v0.13.0/advanced.html)
* [Proxies](https://curl-cffi.readthedocs.io/en/v0.13.0/advanced.html#proxies)
* [Low-level curl API](https://curl-cffi.readthedocs.io/en/v0.13.0/advanced.html#low-level-curl-api)
* [Using `CURLOPT_*` in requests API](https://curl-cffi.readthedocs.io/en/v0.13.0/advanced.html#using-curlopt-in-requests-api)
* [Selecting http version](https://curl-cffi.readthedocs.io/en/v0.13.0/advanced.html#selecting-http-version)
* [Keeping session alive in http/2](https://curl-cffi.readthedocs.io/en/v0.13.0/advanced.html#keeping-session-alive-in-http-2)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.13.0/vs-requests.html)
* [Transports and Adapters](https://curl-cffi.readthedocs.io/en/v0.13.0/vs-requests.html#transports-and-adapters)
* [Cookies](https://curl-cffi.readthedocs.io/en/v0.13.0/cookies.html)
* [Save and load cookies](https://curl-cffi.readthedocs.io/en/v0.13.0/cookies.html#save-and-load-cookies)
* [Discard cookies when using Session](https://curl-cffi.readthedocs.io/en/v0.13.0/cookies.html#discard-cookies-when-using-session)
* [Community](https://curl-cffi.readthedocs.io/en/v0.13.0/community.html)
* [Scrapy integrations](https://curl-cffi.readthedocs.io/en/v0.13.0/community.html#scrapy-integrations)
* [Using with eventlet/gevent](https://curl-cffi.readthedocs.io/en/v0.13.0/community.html#using-with-eventlet-gevent)
* [As a urllib3/requests adapter](https://curl-cffi.readthedocs.io/en/v0.13.0/community.html#as-a-urllib3-requests-adapter)
* [As a httpx transport](https://curl-cffi.readthedocs.io/en/v0.13.0/community.html#as-a-httpx-transport)
* [API References](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html)
* [curl low levl APIs](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl-low-levl-apis)
* [requests-like API](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#requests-like-api)
* [Asyncio](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#asyncio)
* [WebSocket](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#websocket)
* [Exceptions and Warnings](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#exceptions-and-warnings)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.13.0/faq.html)
* [What does the pro version offer? Is the open source project still maintained?](https://curl-cffi.readthedocs.io/en/v0.13.0/faq.html#what-does-the-pro-version-offer-is-the-open-source-project-still-maintained)
* [Why does the JA3 fingerprints change for Chrome 110+ impersonation?](https://curl-cffi.readthedocs.io/en/v0.13.0/faq.html#why-does-the-ja3-fingerprints-change-for-chrome-110-impersonation)
* [Can I bypass Cloudflare with this project? or any other specific site.](https://curl-cffi.readthedocs.io/en/v0.13.0/faq.html#can-i-bypass-cloudflare-with-this-project-or-any-other-specific-site)
* [I’m getting certs errors](https://curl-cffi.readthedocs.io/en/v0.13.0/faq.html#i-m-getting-certs-errors)
* [ErrCode: 77, Reason: error setting certificate verify locations](https://curl-cffi.readthedocs.io/en/v0.13.0/faq.html#errcode-77-reason-error-setting-certificate-verify-locations)
* [How to use with fiddler/charles to intercept content](https://curl-cffi.readthedocs.io/en/v0.13.0/faq.html#how-to-use-with-fiddler-charles-to-intercept-content)
* [ErrCode: 92, Reason: ‘HTTP/2 stream 0 was not closed cleanly: PROTOCOL\_ERROR (err 1)’](https://curl-cffi.readthedocs.io/en/v0.13.0/faq.html#errcode-92-reason-http-2-stream-0-was-not-closed-cleanly-protocol-error-err-1)
* [Packaging with PyInstaller](https://curl-cffi.readthedocs.io/en/v0.13.0/faq.html#packaging-with-pyinstaller)
* [How to change the order of headers?](https://curl-cffi.readthedocs.io/en/v0.13.0/faq.html#how-to-change-the-order-of-headers)
* [How to deal with encoding/decoding errors?](https://curl-cffi.readthedocs.io/en/v0.13.0/faq.html#how-to-deal-with-encoding-decoding-errors)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.13.0/changelog.html)
* [Development and contributing](https://curl-cffi.readthedocs.io/en/v0.13.0/dev.html)
* [Contributing](https://curl-cffi.readthedocs.io/en/v0.13.0/dev.html#contributing)
[Discuss on Telegram](https://t.me/+lL9n33eZp480MGM1)
curl\_cffi is a 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/)
.
Unlike other pure Python http clients like `httpx` or `requests`, `curl_cffi` can impersonate browsers’ TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try.
If you are looking for Python http3 clients, curl\_cffi added http3 support since `v0.11`.
Sponsors[¶](https://curl-cffi.readthedocs.io/en/v0.13.0/#sponsors "Link to this heading")
------------------------------------------------------------------------------------------
### Bypass Cloudflare with API[¶](https://curl-cffi.readthedocs.io/en/v0.13.0/#bypass-cloudflare-with-api "Link to this heading")
[](https://yescaptcha.com/i/stfnIO)
[Yescaptcha](https://yescaptcha.com/i/stfnIO)
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.
You can also click [here](https://buymeacoffee.com/yifei)
to buy me a coffee.
Features[¶](https://curl-cffi.readthedocs.io/en/v0.13.0/#features "Link to this heading")
------------------------------------------------------------------------------------------
* 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 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 & 3.0, which requests does not.
* Supports websocket.
| | | | | | |
| --- | --- | --- | --- | --- | --- |Feature matrix[¶](https://curl-cffi.readthedocs.io/en/v0.13.0/#id2 "Link to this table")
| | requests | aiohttp | httpx | pycurl | curl\_cffi |
| --- | --- | --- | --- | --- | --- |
| http2 | ❌ | ❌ | ✅ | ✅ | ✅ |
| http3 | ❌ | ❌ | ❌ | ✅ | ✅ |
| sync | ✅ | ❌ | ✅ | ✅ | ✅ |
| async | ❌ | ✅ | ✅ | ❌ | ✅ |
| websocket | ❌ | ✅ | ❌ | ❌ | ✅ |
| fingerprints | ❌ | ❌ | ❌ | ❌ | ✅ |
| speed | 🐇 | 🐇🐇 | 🐇 | 🐇🐇 | 🐇🐇 |
Notes:
1. For pycurl, you need a http/3 enabled libcurl, while curl\_cffi packages libcurl-impersonate inside Python wheels.
2. Full http/3 supported was added in v0.12.0.
Install[¶](https://curl-cffi.readthedocs.io/en/v0.13.0/#install "Link to this heading")
----------------------------------------------------------------------------------------
pip install curl\_cffi \--upgrade
For more details, see [Quick Start](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html)
.
Documentation[¶](https://curl-cffi.readthedocs.io/en/v0.13.0/#documentation "Link to this heading")
----------------------------------------------------------------------------------------------------
You can first check out [Quick Start](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html)
. Then the impersonate.
For advanced topics, checkout [Cookies](https://curl-cffi.readthedocs.io/en/v0.13.0/cookies.html)
, [Asyncio](https://curl-cffi.readthedocs.io/en/v0.13.0/asyncio.html)
and [WebSockets](https://curl-cffi.readthedocs.io/en/v0.13.0/websockets.html)
.
You can also find common use cases in the [examples](https://github.com/lexiforest/curl_cffi/tree/main/examples)
directory.
Finally, if something is missing from the tutorial, you can always find them in the [API References](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html)
.
If you have any questions, be sure to check out the [FAQ](https://curl-cffi.readthedocs.io/en/v0.13.0/faq.html)
section before opening an issue.
Indices and tables[¶](https://curl-cffi.readthedocs.io/en/v0.13.0/#indices-and-tables "Link to this heading")
==============================================================================================================
* [Index](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html)
* [Module Index](https://curl-cffi.readthedocs.io/en/v0.13.0/py-modindex.html)
* [Search Page](https://curl-cffi.readthedocs.io/en/v0.13.0/search.html)
### [Table of Contents](https://curl-cffi.readthedocs.io/en/v0.13.0/#)
* [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/v0.13.0/#)
* [Sponsors](https://curl-cffi.readthedocs.io/en/v0.13.0/#sponsors)
* [Bypass Cloudflare with API](https://curl-cffi.readthedocs.io/en/v0.13.0/#bypass-cloudflare-with-api)
* [Features](https://curl-cffi.readthedocs.io/en/v0.13.0/#features)
* [Install](https://curl-cffi.readthedocs.io/en/v0.13.0/#install)
* [Documentation](https://curl-cffi.readthedocs.io/en/v0.13.0/#documentation)
* [Indices and tables](https://curl-cffi.readthedocs.io/en/v0.13.0/#indices-and-tables)
#### Next topic
[Quick Start](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html "next chapter")
### This Page
* [Show Source](https://curl-cffi.readthedocs.io/en/v0.13.0/_sources/index.rst.txt)
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html "Quick Start")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.13.0/#)
»
* [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/v0.13.0/)
---
# curl_cffi’s documentation — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html "Quick Start")
|
* [Top](https://curl-cffi.readthedocs.io/en/v0.12.0/#)
»
* [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/v0.12.0/)
curl\_cffi’s documentation[¶](https://curl-cffi.readthedocs.io/en/v0.12.0/#curl-cffi-s-documentation "Link to this heading")
=============================================================================================================================
Contents:
* [Quick Start](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html)
* [Install](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#install)
* [requests-like](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#requests-like)
* [Asyncio](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#asyncio)
* [WebSockets](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#websockets)
* [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/_index.html)
* [What is TLS and http/2, http/3 fingerprinting?](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/fingerprint.html)
* [Supported browser impersonate targets](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/targets.html)
* [Which target version to use?](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/targets.html#which-target-version-to-use)
* [How to use my own fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/customize.html)
* [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/psk.html)
* [Impersonation FAQ](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/faq.html)
* [Advanced Topics](https://curl-cffi.readthedocs.io/en/v0.12.0/advanced.html)
* [Proxies](https://curl-cffi.readthedocs.io/en/v0.12.0/advanced.html#proxies)
* [Low-level curl API](https://curl-cffi.readthedocs.io/en/v0.12.0/advanced.html#low-level-curl-api)
* [Using `CURLOPT_*` in requests API](https://curl-cffi.readthedocs.io/en/v0.12.0/advanced.html#using-curlopt-in-requests-api)
* [Selecting http version](https://curl-cffi.readthedocs.io/en/v0.12.0/advanced.html#selecting-http-version)
* [Keeping session alive in http/2](https://curl-cffi.readthedocs.io/en/v0.12.0/advanced.html#keeping-session-alive-in-http-2)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.12.0/vs-requests.html)
* [Transports and Adapters](https://curl-cffi.readthedocs.io/en/v0.12.0/vs-requests.html#transports-and-adapters)
* [Cookies](https://curl-cffi.readthedocs.io/en/v0.12.0/cookies.html)
* [Save and load cookies](https://curl-cffi.readthedocs.io/en/v0.12.0/cookies.html#save-and-load-cookies)
* [Discard cookies when using Session](https://curl-cffi.readthedocs.io/en/v0.12.0/cookies.html#discard-cookies-when-using-session)
* [Community](https://curl-cffi.readthedocs.io/en/v0.12.0/community.html)
* [Scrapy integrations](https://curl-cffi.readthedocs.io/en/v0.12.0/community.html#scrapy-integrations)
* [Using with eventlet/gevent](https://curl-cffi.readthedocs.io/en/v0.12.0/community.html#using-with-eventlet-gevent)
* [As a urllib3/requests adapter](https://curl-cffi.readthedocs.io/en/v0.12.0/community.html#as-a-urllib3-requests-adapter)
* [As a httpx transport](https://curl-cffi.readthedocs.io/en/v0.12.0/community.html#as-a-httpx-transport)
* [API References](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html)
* [curl low levl APIs](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl-low-levl-apis)
* [requests-like API](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#requests-like-api)
* [Asyncio](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#asyncio)
* [WebSocket](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#websocket)
* [Exceptions and Warnings](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#exceptions-and-warnings)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.12.0/faq.html)
* [What does the pro version offer? Is the open source project still maintained?](https://curl-cffi.readthedocs.io/en/v0.12.0/faq.html#what-does-the-pro-version-offer-is-the-open-source-project-still-maintained)
* [Why does the JA3 fingerprints change for Chrome 110+ impersonation?](https://curl-cffi.readthedocs.io/en/v0.12.0/faq.html#why-does-the-ja3-fingerprints-change-for-chrome-110-impersonation)
* [Can I bypass Cloudflare with this project? or any other specific site.](https://curl-cffi.readthedocs.io/en/v0.12.0/faq.html#can-i-bypass-cloudflare-with-this-project-or-any-other-specific-site)
* [I’m getting certs errors](https://curl-cffi.readthedocs.io/en/v0.12.0/faq.html#i-m-getting-certs-errors)
* [ErrCode: 77, Reason: error setting certificate verify locations](https://curl-cffi.readthedocs.io/en/v0.12.0/faq.html#errcode-77-reason-error-setting-certificate-verify-locations)
* [How to use with fiddler/charles to intercept content](https://curl-cffi.readthedocs.io/en/v0.12.0/faq.html#how-to-use-with-fiddler-charles-to-intercept-content)
* [ErrCode: 92, Reason: ‘HTTP/2 stream 0 was not closed cleanly: PROTOCOL\_ERROR (err 1)’](https://curl-cffi.readthedocs.io/en/v0.12.0/faq.html#errcode-92-reason-http-2-stream-0-was-not-closed-cleanly-protocol-error-err-1)
* [Packaging with PyInstaller](https://curl-cffi.readthedocs.io/en/v0.12.0/faq.html#packaging-with-pyinstaller)
* [How to change the order of headers?](https://curl-cffi.readthedocs.io/en/v0.12.0/faq.html#how-to-change-the-order-of-headers)
* [How to deal with encoding/decoding errors?](https://curl-cffi.readthedocs.io/en/v0.12.0/faq.html#how-to-deal-with-encoding-decoding-errors)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.12.0/changelog.html)
* [Development and contributing](https://curl-cffi.readthedocs.io/en/v0.12.0/dev.html)
* [Contributing](https://curl-cffi.readthedocs.io/en/v0.12.0/dev.html#contributing)
[Discuss on Telegram](https://t.me/+lL9n33eZp480MGM1)
curl\_cffi is a 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/)
.
Unlike other pure Python http clients like `httpx` or `requests`, `curl_cffi` can impersonate browsers’ TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try.
If you are looking for Python http3 clients, curl\_cffi added http3 support since `v0.11`.
Sponsors[¶](https://curl-cffi.readthedocs.io/en/v0.12.0/#sponsors "Link to this heading")
------------------------------------------------------------------------------------------
### SerpAPI[¶](https://curl-cffi.readthedocs.io/en/v0.12.0/#serpapi "Link to this heading")
[](https://serpapi.com/)
Scrape Google and other search engines from [SerpApi](https://serpapi.com/)
’s fast, easy, and complete API. 0.66s average response time (≤ 0.5s for Ludicrous Speed Max accounts), 99.95% SLAs, pay for successful responses only.
### Bypass Cloudflare with API[¶](https://curl-cffi.readthedocs.io/en/v0.12.0/#bypass-cloudflare-with-api "Link to this heading")
[](https://yescaptcha.com/i/stfnIO)
[Yescaptcha](https://yescaptcha.com/i/stfnIO)
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.
### Easy Captcha Bypass for Scraping[¶](https://curl-cffi.readthedocs.io/en/v0.12.0/#easy-captcha-bypass-for-scraping "Link to this heading")
[](https://dashboard.capsolver.com/passport/register?inviteCode=0FLEay4iroNC)
[CapSolver](https://dashboard.capsolver.com/passport/register?inviteCode=0FLEay4iroNC)
is an AI-powered tool that easily bypasses Captchas, allowing uninterrupted access to public data. It supports a variety of Captchas and works seamlessly with `curl_cffi`, Puppeteer, Playwright, and more. Fast, reliable, and cost-effective. Plus, `curl_cffi` users can use the code **“CURL”** to get an extra 6% balance! and register [here](https://dashboard.capsolver.com/passport/register?inviteCode=0FLEay4iroNC)
You can also click [here](https://buymeacoffee.com/yifei)
to buy me a coffee.
Features[¶](https://curl-cffi.readthedocs.io/en/v0.12.0/#features "Link to this heading")
------------------------------------------------------------------------------------------
* 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 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 & 3.0, which requests does not.
* Supports websocket.
| | | | | | |
| --- | --- | --- | --- | --- | --- |Feature matrix[¶](https://curl-cffi.readthedocs.io/en/v0.12.0/#id4 "Link to this table")
| | requests | aiohttp | httpx | pycurl | curl\_cffi |
| --- | --- | --- | --- | --- | --- |
| http2 | ❌ | ❌ | ✅ | ✅ | ✅ |
| http3 | ❌ | ❌ | ❌ | ☑️ | ☑️ |
| sync | ✅ | ❌ | ✅ | ✅ | ✅ |
| async | ❌ | ✅ | ✅ | ❌ | ✅ |
| websocket | ❌ | ✅ | ❌ | ❌ | ✅ |
| fingerprints | ❌ | ❌ | ❌ | ❌ | ✅ |
| speed | 🐇 | 🐇🐇 | 🐇 | 🐇🐇 | 🐇🐇 |
Notes:
1. For pycurl, you need a http/3 enabled libcurl to make it work, while curl\_cffi packages libcurl-impersonate inside Python wheels.
2. Since v0.11.0. However, only Linux and macOS are supported, Windows is not supported due to failed building of ngtcp2.
Install[¶](https://curl-cffi.readthedocs.io/en/v0.12.0/#install "Link to this heading")
----------------------------------------------------------------------------------------
pip install curl\_cffi \--upgrade
For more details, see [Quick Start](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html)
.
Documentation[¶](https://curl-cffi.readthedocs.io/en/v0.12.0/#documentation "Link to this heading")
----------------------------------------------------------------------------------------------------
You can first check out [Quick Start](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html)
. Then the impersonate.
For advanced topics, checkout [Cookies](https://curl-cffi.readthedocs.io/en/v0.12.0/cookies.html)
, [Asyncio](https://curl-cffi.readthedocs.io/en/v0.12.0/asyncio.html)
and [WebSockets](https://curl-cffi.readthedocs.io/en/v0.12.0/websockets.html)
.
You can also find common use cases in the [examples](https://github.com/lexiforest/curl_cffi/tree/main/examples)
directory.
Finally, if something is missing from the tutorial, you can always find them in the [API References](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html)
.
If you have any questions, be sure to check out the [FAQ](https://curl-cffi.readthedocs.io/en/v0.12.0/faq.html)
section before opening an issue.
Indices and tables[¶](https://curl-cffi.readthedocs.io/en/v0.12.0/#indices-and-tables "Link to this heading")
==============================================================================================================
* [Index](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html)
* [Module Index](https://curl-cffi.readthedocs.io/en/v0.12.0/py-modindex.html)
* [Search Page](https://curl-cffi.readthedocs.io/en/v0.12.0/search.html)
### [Table of Contents](https://curl-cffi.readthedocs.io/en/v0.12.0/#)
* [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/v0.12.0/#)
* [Sponsors](https://curl-cffi.readthedocs.io/en/v0.12.0/#sponsors)
* [SerpAPI](https://curl-cffi.readthedocs.io/en/v0.12.0/#serpapi)
* [Bypass Cloudflare with API](https://curl-cffi.readthedocs.io/en/v0.12.0/#bypass-cloudflare-with-api)
* [Easy Captcha Bypass for Scraping](https://curl-cffi.readthedocs.io/en/v0.12.0/#easy-captcha-bypass-for-scraping)
* [Features](https://curl-cffi.readthedocs.io/en/v0.12.0/#features)
* [Install](https://curl-cffi.readthedocs.io/en/v0.12.0/#install)
* [Documentation](https://curl-cffi.readthedocs.io/en/v0.12.0/#documentation)
* [Indices and tables](https://curl-cffi.readthedocs.io/en/v0.12.0/#indices-and-tables)
#### Next topic
[Quick Start](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html "next chapter")
### This Page
* [Show Source](https://curl-cffi.readthedocs.io/en/v0.12.0/_sources/index.rst.txt)
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html "Quick Start")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.12.0/#)
»
* [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/v0.12.0/)
---
# curl_cffi
* [](https://curl-cffi.readthedocs.io/en/v0.5.8.1/)
»
* curl\_cffi
* * *
curl\_cffi
==========
Python binding for [curl-impersonate](https://github.com/lwthiker/curl-impersonate)
via [cffi](https://cffi.readthedocs.io/en/latest/)
.
[Documentation](https://curl-cffi.readthedocs.io/)
| [中文 README](https://github.com/yifeikong/curl_cffi/blob/master/README-zh.md)
Unlike other pure python http clients like `httpx` or `requests`, `curl_cffi` can impersonate browsers' TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try.
Features
--------
* Supports JA3/TLS and http2 fingerprints impersonation.
* Much faster than requests/httpx/tls\_client, on par with aiohttp/pycurl, see [benchmarks](https://github.com/yifeikong/curl_cffi/tree/master/benchmark)
.
* Mimics 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.
Install
-------
pip install curl_cffi --upgrade
This should work on Linux(x86\_64/aarch64), macOS(Intel/Apple Silicon) and Windows(amd64). If it does not work on you platform, you may need to compile and install `curl-impersonate` first and set some environment variables like `LD_LIBRARY_PATH`.
Usage
-----
### requests-like
from curl_cffi import requests
# Notice the impersonate parameter
r = requests.get("https://tls.browserleaks.com/json", impersonate="chrome110")
print(r.json())
# output: {..., "ja3n_hash": "aa56c057ad164ec4fdcb7a5a283be9fc", ...}
# the js3n fingerprint should be the same as target browser
# http/socks proxies are supported
proxies = {"https": "http://localhost:3128"}
r = requests.get("https://tls.browserleaks.com/json", impersonate="chrome110", proxies=proxies)
proxies = {"https": "socks://localhost:3128"}
r = requests.get("https://tls.browserleaks.com/json", impersonate="chrome110", proxies=proxies)
### Sessions
# sessions are supported
s = requests.Session()
# httpbin is a http test website
s.get("https://httpbin.org/cookies/set/foo/bar")
print(s.cookies)
# ]>
r = s.get("https://httpbin.org/cookies")
print(r.json())
# {'cookies': {'foo': 'bar'}}
Supported impersonate versions, as supported by [curl-impersonate](https://github.com/lwthiker/curl-impersonate)
:
* chrome99
* chrome100
* chrome101
* chrome104
* chrome107
* chrome110
* chrome99\_android
* edge99
* edge101
* safari15\_3
* safari15\_5
### asyncio
from curl_cffi.requests import AsyncSession
async with AsyncSession() as s:
r = await s.get("https://example.com")
More concurrency:
import asyncio
from curl_cffi.requests import AsyncSession
urls = [\
"https://googel.com/",\
"https://facebook.com/",\
"https://twitter.com/",\
]
async with AsyncSession() as s:
tasks = []
for url in urls:
task = s.get("https://example.com")
tasks.append(task)
results = await asyncio.gather(*tasks)
### curl-like
Alternatively, you can use the low-level curl-like API:
from curl_cffi import Curl, CurlOpt
from io import BytesIO
buffer = BytesIO()
c = Curl()
c.setopt(CurlOpt.URL, b'https://tls.browserleaks.com/json')
c.setopt(CurlOpt.WRITEDATA, buffer)
c.impersonate("chrome110")
c.perform()
c.close()
body = buffer.getvalue()
print(body.decode())
See the [docs](https://curl-cffi.readthedocs.io/)
for more details.
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.
---
# curl_cffi
* [](https://curl-cffi.readthedocs.io/en/v0.5.8/)
»
* curl\_cffi
* * *
curl\_cffi
==========
Python binding for [curl-impersonate](https://github.com/lwthiker/curl-impersonate)
via [cffi](https://cffi.readthedocs.io/en/latest/)
.
[Documentation](https://curl-cffi.readthedocs.io/)
| [中文 README](https://github.com/yifeikong/curl_cffi/blob/master/README-zh.md)
Unlike other pure python http clients like `httpx` or `requests`, `curl_cffi` can impersonate browsers' TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try.
Features
--------
* Supports JA3/TLS and http2 fingerprints impersonation.
* Much faster than requests/httpx/tls\_client, on par with aiohttp/pycurl, see [benchmarks](https://github.com/yifeikong/curl_cffi/tree/master/benchmark)
.
* Mimics 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.
Install
-------
pip install curl_cffi --upgrade
This should work on Linux(x86\_64/aarch64), macOS(Intel/Apple Silicon) and Windows(amd64). If it does not work on you platform, you may need to compile and install `curl-impersonate` first and set some environment variables like `LD_LIBRARY_PATH`.
Usage
-----
### requests-like
from curl_cffi import requests
# Notice the impersonate parameter
r = requests.get("https://tls.browserleaks.com/json", impersonate="chrome110")
print(r.json())
# output: {..., "ja3n_hash": "aa56c057ad164ec4fdcb7a5a283be9fc", ...}
# the js3n fingerprint should be the same as target browser
# http/socks proxies are supported
proxies = {"https": "http://localhost:3128"}
r = requests.get("https://tls.browserleaks.com/json", impersonate="chrome110", proxies=proxies)
proxies = {"https": "socks://localhost:3128"}
r = requests.get("https://tls.browserleaks.com/json", impersonate="chrome110", proxies=proxies)
### Sessions
# sessions are supported
s = requests.Session()
# httpbin is a http test website
s.get("https://httpbin.org/cookies/set/foo/bar")
print(s.cookies)
# ]>
r = s.get("https://httpbin.org/cookies")
print(r.json())
# {'cookies': {'foo': 'bar'}}
Supported impersonate versions, as supported by [curl-impersonate](https://github.com/lwthiker/curl-impersonate)
:
* chrome99
* chrome100
* chrome101
* chrome104
* chrome107
* chrome110
* chrome99\_android
* edge99
* edge101
* safari15\_3
* safari15\_5
### asyncio
from curl_cffi.requests import AsyncSession
async with AsyncSession() as s:
r = await s.get("https://example.com")
More concurrency:
import asyncio
from curl_cffi.requests import AsyncSession
urls = [\
"https://googel.com/",\
"https://facebook.com/",\
"https://twitter.com/",\
]
async with AsyncSession() as s:
tasks = []
for url in urls:
task = s.get("https://example.com")
tasks.append(task)
results = await asyncio.gather(*tasks)
### curl-like
Alternatively, you can use the low-level curl-like API:
from curl_cffi import Curl, CurlOpt
from io import BytesIO
buffer = BytesIO()
c = Curl()
c.setopt(CurlOpt.URL, b'https://tls.browserleaks.com/json')
c.setopt(CurlOpt.WRITEDATA, buffer)
c.impersonate("chrome110")
c.perform()
c.close()
body = buffer.getvalue()
print(body.decode())
See the [docs](https://curl-cffi.readthedocs.io/)
for more details.
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.
---
# curl_cffi
* [](https://curl-cffi.readthedocs.io/en/v0.5.9/)
* curl\_cffi
* * *
curl\_cffi
==========
Python binding for [curl-impersonate](https://github.com/lwthiker/curl-impersonate)
via [cffi](https://cffi.readthedocs.io/en/latest/)
.
[Documentation](https://curl-cffi.readthedocs.io/)
| [中文 README](https://github.com/yifeikong/curl_cffi/blob/master/README-zh.md)
Unlike other pure python http clients like `httpx` or `requests`, `curl_cffi` can impersonate browsers' TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try.
Features
--------
* Supports JA3/TLS and http2 fingerprints impersonation.
* Much faster than requests/httpx/tls\_client, on par with aiohttp/pycurl, see [benchmarks](https://github.com/yifeikong/curl_cffi/tree/master/benchmark)
.
* Mimics 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.
Install
-------
pip install curl_cffi --upgrade
This should work on Linux(x86\_64/aarch64), macOS(Intel/Apple Silicon) and Windows(amd64). If it does not work on you platform, you may need to compile and install `curl-impersonate` first and set some environment variables like `LD_LIBRARY_PATH`.
To install beta releases:
pip install curl_cffi --pre
Usage
-----
### requests-like
from curl_cffi import requests
# Notice the impersonate parameter
r = requests.get("https://tls.browserleaks.com/json", impersonate="chrome110")
print(r.json())
# output: {..., "ja3n_hash": "aa56c057ad164ec4fdcb7a5a283be9fc", ...}
# the js3n fingerprint should be the same as target browser
# http/socks proxies are supported
proxies = {"https": "http://localhost:3128"}
r = requests.get("https://tls.browserleaks.com/json", impersonate="chrome110", proxies=proxies)
proxies = {"https": "socks://localhost:3128"}
r = requests.get("https://tls.browserleaks.com/json", impersonate="chrome110", proxies=proxies)
### Sessions
# sessions are supported
s = requests.Session()
# httpbin is a http test website
s.get("https://httpbin.org/cookies/set/foo/bar")
print(s.cookies)
# ]>
r = s.get("https://httpbin.org/cookies")
print(r.json())
# {'cookies': {'foo': 'bar'}}
Supported impersonate versions, as supported by [curl-impersonate](https://github.com/lwthiker/curl-impersonate)
:
* chrome99
* chrome100
* chrome101
* chrome104
* chrome107
* chrome110
* chrome99\_android
* edge99
* edge101
* safari15\_3
* safari15\_5
### asyncio
from curl_cffi.requests import AsyncSession
async with AsyncSession() as s:
r = await s.get("https://example.com")
More concurrency:
import asyncio
from curl_cffi.requests import AsyncSession
urls = [\
"https://googel.com/",\
"https://facebook.com/",\
"https://twitter.com/",\
]
async with AsyncSession() as s:
tasks = []
for url in urls:
task = s.get("https://example.com")
tasks.append(task)
results = await asyncio.gather(*tasks)
### curl-like
Alternatively, you can use the low-level curl-like API:
from curl_cffi import Curl, CurlOpt
from io import BytesIO
buffer = BytesIO()
c = Curl()
c.setopt(CurlOpt.URL, b'https://tls.browserleaks.com/json')
c.setopt(CurlOpt.WRITEDATA, buffer)
c.impersonate("chrome110")
c.perform()
c.close()
body = buffer.getvalue()
print(body.decode())
See the [docs](https://curl-cffi.readthedocs.io/)
for more details.
If you are using scrapy, check out this middleware: [tieyongjie/scrapy-fingerprint](https://github.com/tieyongjie/scrapy-fingerprint)
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.
---
# Welcome to curl_cffi’s documentation! — curl_cffi documentation
Welcome to curl\_cffi’s documentation
===================================================================================================================================================
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.6.3/install.html)
* [Via pip](https://curl-cffi.readthedocs.io/en/v0.6.3/install.html#via-pip)
* [Beta versions](https://curl-cffi.readthedocs.io/en/v0.6.3/install.html#beta-versions)
* [Latest](https://curl-cffi.readthedocs.io/en/v0.6.3/install.html#latest)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.6.3/impersonate.html)
* [Supported browser versions](https://curl-cffi.readthedocs.io/en/v0.6.3/impersonate.html#supported-browser-versions)
* [Which version to use?](https://curl-cffi.readthedocs.io/en/v0.6.3/impersonate.html#which-version-to-use)
* [How to customize my fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.6.3/impersonate.html#how-to-customize-my-fingerprints-e-g-okhttp)
* [Should I randomize my fingerprints for each request?](https://curl-cffi.readthedocs.io/en/v0.6.3/impersonate.html#should-i-randomize-my-fingerprints-for-each-request)
* [Can I change JS fingerprints with this library?](https://curl-cffi.readthedocs.io/en/v0.6.3/impersonate.html#can-i-change-js-fingerprints-with-this-library)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.6.3/advanced.html)
* [low-level curl API](https://curl-cffi.readthedocs.io/en/v0.6.3/advanced.html#low-level-curl-api)
* [scrapy integrations](https://curl-cffi.readthedocs.io/en/v0.6.3/advanced.html#scrapy-integrations)
* [Using with eventlet/gevent](https://curl-cffi.readthedocs.io/en/v0.6.3/advanced.html#using-with-eventlet-gevent)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.6.3/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.6.3/faq.html)
* [Why does the JA3 fingerprints change for Chrome 110+ impersonation?](https://curl-cffi.readthedocs.io/en/v0.6.3/faq.html#why-does-the-ja3-fingerprints-change-for-chrome-110-impersonation)
* [Can I bypass Cloudflare with this project? or any other specific site.](https://curl-cffi.readthedocs.io/en/v0.6.3/faq.html#can-i-bypass-cloudflare-with-this-project-or-any-other-specific-site)
* [I’m getting certs errors](https://curl-cffi.readthedocs.io/en/v0.6.3/faq.html#i-m-getting-certs-errors)
* [ErrCode: 77, Reason: error setting certificate verify locations](https://curl-cffi.readthedocs.io/en/v0.6.3/faq.html#errcode-77-reason-error-setting-certificate-verify-locations)
* [How to use with fiddler/charles to intercept content](https://curl-cffi.readthedocs.io/en/v0.6.3/faq.html#how-to-use-with-fiddler-charles-to-intercept-content)
* [ErrCode: 92, Reason: ‘HTTP/2 stream 0 was not closed cleanly: PROTOCOL\_ERROR (err 1)’](https://curl-cffi.readthedocs.io/en/v0.6.3/faq.html#errcode-92-reason-http-2-stream-0-was-not-closed-cleanly-protocol-error-err-1)
* [Packaging with PyInstaller](https://curl-cffi.readthedocs.io/en/v0.6.3/faq.html#packaging-with-pyinstaller)
* [How to set proxy?](https://curl-cffi.readthedocs.io/en/v0.6.3/faq.html#how-to-set-proxy)
* [How to change the order of headers?](https://curl-cffi.readthedocs.io/en/v0.6.3/faq.html#how-to-change-the-order-of-headers)
* [API References](https://curl-cffi.readthedocs.io/en/v0.6.3/api.html)
* [curl low levl APIs](https://curl-cffi.readthedocs.io/en/v0.6.3/api.html#curl-low-levl-apis)
* [requests API](https://curl-cffi.readthedocs.io/en/v0.6.3/api.html#requests-api)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.6.3/changelog.html)
* [v0.6](https://curl-cffi.readthedocs.io/en/v0.6.3/changelog.html#v0-6)
* [v0.5](https://curl-cffi.readthedocs.io/en/v0.6.3/changelog.html#v0-5)
* [v0.4](https://curl-cffi.readthedocs.io/en/v0.6.3/changelog.html#v0-4)
* [v0.3](https://curl-cffi.readthedocs.io/en/v0.6.3/changelog.html#v0-3)
[中文 README](https://github.com/yifeikong/curl_cffi/blob/main/README-zh.md)
| [Discuss on Telegram](https://t.me/+lL9n33eZp480MGM1)
curl\_cffi is a Python binding for [curl-impersonate](https://github.com/yifeikong/curl-impersonate)
via [cffi](https://cffi.readthedocs.io/en/latest/)
.
Unlike other pure Python http clients like `httpx` or `requests`, `curl_cffi` can impersonate browsers’ TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try.
* * *
[](https://scrapfly.io/?utm_source=github&utm_medium=sponsoring&utm_campaign=curl_cffi)
[Scrapfly](https://scrapfly.io/?utm_source=github&utm_medium=sponsoring&utm_campaign=curl_cffi)
is an enterprise-grade solution providing Web Scraping API that aims to simplify the scraping process by managing everything: real browser rendering, rotating proxies, and fingerprints (TLS, HTTP, browser) to bypass all major anti-bots. Scrapfly also unlocks the observability by providing an analytical dashboard and measuring the success rate/block rate in details.
Scrapfly is a good solution if you are looking for a cloud-managed solution for `curl_cffi`. If you are managing TLS/HTTP fingerprint by yourself with `curl_cffi`, they also maintain [this tool](https://scrapfly.io/web-scraping-tools/curl-python/curl_cffi)
to convert curl command into python curl\_cffi code!
* * *
Features[¶](https://curl-cffi.readthedocs.io/en/v0.6.3/#features "Link to this heading")
-----------------------------------------------------------------------------------------
* Supports JA3/TLS and http2 fingerprints impersonation.
* Much faster than requests/httpx, on par with aiohttp/pycurl, see [benchmarks](https://github.com/yifeikong/curl_cffi/tree/main/benchmark)
.
* Mimics 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 websocket.
| | | | | | |
| --- | --- | --- | --- | --- | --- |Feature matrix[¶](https://curl-cffi.readthedocs.io/en/v0.6.3/#id3 "Link to this table")
| | requests | aiohttp | httpx | pycurl | curl\_cffi |
| --- | --- | --- | --- | --- | --- |
| http2 | ❌ | ❌ | ✅ | ✅ | ✅ |
| sync | ✅ | ❌ | ✅ | ✅ | ✅ |
| async | ❌ | ✅ | ✅ | ❌ | ✅ |
| websocket | ❌ | ✅ | ❌ | ❌ | ✅ |
| fingerprints | ❌ | ❌ | ❌ | ❌ | ✅ |
| speed | 🐇 | 🐇🐇 | 🐇 | 🐇🐇 | 🐇🐇 |
Install[¶](https://curl-cffi.readthedocs.io/en/v0.6.3/#install "Link to this heading")
---------------------------------------------------------------------------------------
pip install curl\_cffi \--upgrade
For more details, see [Install](https://curl-cffi.readthedocs.io/en/v0.6.3/install.html)
.
Basic Usage[¶](https://curl-cffi.readthedocs.io/en/v0.6.3/#basic-usage "Link to this heading")
-----------------------------------------------------------------------------------------------
### requests-like[¶](https://curl-cffi.readthedocs.io/en/v0.6.3/#requests-like "Link to this heading")
from curl\_cffi import requests
url \= "https://tls.browserleaks.com/json"
\# Notice the impersonate parameter
r \= requests.get(url, impersonate\="chrome")
print(r.json())
\# output: {..., "ja3n\_hash": "aa56c057ad164ec4fdcb7a5a283be9fc", ...}
\# the js3n fingerprint should be the same as target browser
\# http/socks proxies are supported
proxies \= {"https": "http://localhost:3128"}
r \= requests.get(url, impersonate\="chrome", proxies\=proxies)
proxies \= {"https": "socks://localhost:3128"}
r \= requests.get(url, impersonate\="chrome", proxies\=proxies)
### Sessions[¶](https://curl-cffi.readthedocs.io/en/v0.6.3/#sessions "Link to this heading")
s \= requests.Session()
\# httpbin is a http test website
s.get("https://httpbin.org/cookies/set/foo/bar")
print(s.cookies)
\# \]>
r \= s.get("https://httpbin.org/cookies")
print(r.json())
\# {'cookies': {'foo': 'bar'}}
### asyncio[¶](https://curl-cffi.readthedocs.io/en/v0.6.3/#asyncio "Link to this heading")
from curl\_cffi.requests import AsyncSession
async with AsyncSession() as s:
r \= await s.get("https://example.com")
More concurrency:
import asyncio
from curl\_cffi.requests 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)
### WebSockets[¶](https://curl-cffi.readthedocs.io/en/v0.6.3/#websockets "Link to this heading")
from curl\_cffi.requests import Session, WebSocket
def on\_message(ws: WebSocket, message):
print(message)
with Session() as s:
ws \= s.ws\_connect(
"wss://api.gemini.com/v1/marketdata/BTCUSD",
on\_message\=on\_message,
)
ws.run\_forever()
Sponsor[¶](https://curl-cffi.readthedocs.io/en/v0.6.3/#sponsor "Link to this heading")
---------------------------------------------------------------------------------------
Click [here](https://buymeacoffee.com/yifei)
to buy me a coffee.
### Bypass Cloudflare with API[¶](https://curl-cffi.readthedocs.io/en/v0.6.3/#bypass-cloudflare-with-api "Link to this heading")
[](https://yescaptcha.com/i/stfnIO)
[Yescaptcha](https://yescaptcha.com/i/stfnIO)
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.
### ScrapeNinja[¶](https://curl-cffi.readthedocs.io/en/v0.6.3/#scrapeninja "Link to this heading")
[](https://scrapeninja.net/?utm_source=github&utm_medium=banner&utm_campaign=cffi)
[ScrapeNinja](https://scrapeninja.net/?utm_source=github&utm_medium=banner&utm_campaign=cffi)
is a web scraping API with two engines: fast, with high performance and TLS fingerprint; and slower with a real browser under the hood.
ScrapeNinja handles headless browsers, proxies, timeouts, retries, and helps with data extraction, so you can just get the data in JSON. Rotating proxies are available out of the box on all subscription plans.
Indices and tables[¶](https://curl-cffi.readthedocs.io/en/v0.6.3/#indices-and-tables "Link to this heading")
=============================================================================================================
* [Index](https://curl-cffi.readthedocs.io/en/v0.6.3/genindex.html)
* [Module Index](https://curl-cffi.readthedocs.io/en/v0.6.3/py-modindex.html)
* [Search Page](https://curl-cffi.readthedocs.io/en/v0.6.3/search.html)
[curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.6.3/#)
===========================================================
### Navigation
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.6.3/install.html)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.6.3/impersonate.html)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.6.3/advanced.html)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.6.3/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.6.3/faq.html)
* [API References](https://curl-cffi.readthedocs.io/en/v0.6.3/api.html)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.6.3/changelog.html)
### Related Topics
* [Documentation overview](https://curl-cffi.readthedocs.io/en/v0.6.3/#)
* Next: [Install](https://curl-cffi.readthedocs.io/en/v0.6.3/install.html "next chapter")
### Quick search
---
# Welcome to curl_cffi’s documentation! — curl_cffi documentation
Welcome to curl\_cffi’s documentation
===================================================================================================================================================
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.8.0/install.html)
* [Via pip](https://curl-cffi.readthedocs.io/en/v0.8.0/install.html#via-pip)
* [Beta versions](https://curl-cffi.readthedocs.io/en/v0.8.0/install.html#beta-versions)
* [Latest](https://curl-cffi.readthedocs.io/en/v0.8.0/install.html#latest)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.8.0/impersonate.html)
* [Supported browser versions](https://curl-cffi.readthedocs.io/en/v0.8.0/impersonate.html#supported-browser-versions)
* [Which version to use?](https://curl-cffi.readthedocs.io/en/v0.8.0/impersonate.html#which-version-to-use)
* [How to use my own fingerprints other than the builtin ones? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.8.0/impersonate.html#how-to-use-my-own-fingerprints-other-than-the-builtin-ones-e-g-okhttp)
* [Should I randomize my fingerprints for each request?](https://curl-cffi.readthedocs.io/en/v0.8.0/impersonate.html#should-i-randomize-my-fingerprints-for-each-request)
* [Can I change JavaScript fingerprints with this library?](https://curl-cffi.readthedocs.io/en/v0.8.0/impersonate.html#can-i-change-javascript-fingerprints-with-this-library)
* [Cookies](https://curl-cffi.readthedocs.io/en/v0.8.0/cookies.html)
* [How to save and load cookies](https://curl-cffi.readthedocs.io/en/v0.8.0/cookies.html#how-to-save-and-load-cookies)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.8.0/advanced.html)
* [low-level curl API](https://curl-cffi.readthedocs.io/en/v0.8.0/advanced.html#low-level-curl-api)
* [scrapy integrations](https://curl-cffi.readthedocs.io/en/v0.8.0/advanced.html#scrapy-integrations)
* [Using with eventlet/gevent](https://curl-cffi.readthedocs.io/en/v0.8.0/advanced.html#using-with-eventlet-gevent)
* [Exceptions](https://curl-cffi.readthedocs.io/en/v0.8.0/exceptions.html)
* [Exceptions](https://curl-cffi.readthedocs.io/en/v0.8.0/exceptions.html#id1)
* [Warnings](https://curl-cffi.readthedocs.io/en/v0.8.0/exceptions.html#warnings)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.8.0/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.8.0/faq.html)
* [Why does the JA3 fingerprints change for Chrome 110+ impersonation?](https://curl-cffi.readthedocs.io/en/v0.8.0/faq.html#why-does-the-ja3-fingerprints-change-for-chrome-110-impersonation)
* [Can I bypass Cloudflare with this project? or any other specific site.](https://curl-cffi.readthedocs.io/en/v0.8.0/faq.html#can-i-bypass-cloudflare-with-this-project-or-any-other-specific-site)
* [I’m getting certs errors](https://curl-cffi.readthedocs.io/en/v0.8.0/faq.html#i-m-getting-certs-errors)
* [ErrCode: 77, Reason: error setting certificate verify locations](https://curl-cffi.readthedocs.io/en/v0.8.0/faq.html#errcode-77-reason-error-setting-certificate-verify-locations)
* [How to use with fiddler/charles to intercept content](https://curl-cffi.readthedocs.io/en/v0.8.0/faq.html#how-to-use-with-fiddler-charles-to-intercept-content)
* [ErrCode: 92, Reason: ‘HTTP/2 stream 0 was not closed cleanly: PROTOCOL\_ERROR (err 1)’](https://curl-cffi.readthedocs.io/en/v0.8.0/faq.html#errcode-92-reason-http-2-stream-0-was-not-closed-cleanly-protocol-error-err-1)
* [Packaging with PyInstaller](https://curl-cffi.readthedocs.io/en/v0.8.0/faq.html#packaging-with-pyinstaller)
* [How to set proxy?](https://curl-cffi.readthedocs.io/en/v0.8.0/faq.html#how-to-set-proxy)
* [How to change the order of headers?](https://curl-cffi.readthedocs.io/en/v0.8.0/faq.html#how-to-change-the-order-of-headers)
* [API References](https://curl-cffi.readthedocs.io/en/v0.8.0/api.html)
* [curl low levl APIs](https://curl-cffi.readthedocs.io/en/v0.8.0/api.html#curl-low-levl-apis)
* [requests API](https://curl-cffi.readthedocs.io/en/v0.8.0/api.html#requests-api)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.8.0/changelog.html)
* [v0.7](https://curl-cffi.readthedocs.io/en/v0.8.0/changelog.html#v0-7)
* [v0.6](https://curl-cffi.readthedocs.io/en/v0.8.0/changelog.html#v0-6)
* [v0.5](https://curl-cffi.readthedocs.io/en/v0.8.0/changelog.html#v0-5)
* [v0.4](https://curl-cffi.readthedocs.io/en/v0.8.0/changelog.html#v0-4)
* [v0.3](https://curl-cffi.readthedocs.io/en/v0.8.0/changelog.html#v0-3)
[Discuss on Telegram](https://t.me/+lL9n33eZp480MGM1)
curl\_cffi is a Python binding for [\`curl-impersonate fork\`\_](https://curl-cffi.readthedocs.io/en/v0.8.0/#id4)
via [cffi](https://cffi.readthedocs.io/en/latest/)
.
Unlike other pure Python http clients like `httpx` or `requests`, `curl_cffi` can impersonate browsers’ TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try.
* * *
[](https://scrapfly.io/?utm_source=github&utm_medium=sponsoring&utm_campaign=curl_cffi)
[Scrapfly](https://scrapfly.io/?utm_source=github&utm_medium=sponsoring&utm_campaign=curl_cffi)
is an enterprise-grade solution providing Web Scraping API that aims to simplify the scraping process by managing everything: real browser rendering, rotating proxies, and fingerprints (TLS, HTTP, browser) to bypass all major anti-bots. Scrapfly also unlocks the observability by providing an analytical dashboard and measuring the success rate/block rate in details.
Scrapfly is a good solution if you are looking for a cloud-managed solution for `curl_cffi`. If you are managing TLS/HTTP fingerprint by yourself with `curl_cffi`, they also maintain a [curl to python converter](https://scrapfly.io/web-scraping-tools/curl-python/curl_cffi)
.
* * *
Features[¶](https://curl-cffi.readthedocs.io/en/v0.8.0/#features "Link to this heading")
-----------------------------------------------------------------------------------------
* Supports JA3/TLS and http2 fingerprints impersonation.
* Much faster than requests/httpx, on par with aiohttp/pycurl, see [benchmarks](https://github.com/lexiforest/curl_cffi/tree/main/benchmark)
.
* Mimics 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 websocket.
| | | | | | |
| --- | --- | --- | --- | --- | --- |Feature matrix[¶](https://curl-cffi.readthedocs.io/en/v0.8.0/#id3 "Link to this table")
| | requests | aiohttp | httpx | pycurl | curl\_cffi |
| --- | --- | --- | --- | --- | --- |
| http2 | ❌ | ❌ | ✅ | ✅ | ✅ |
| sync | ✅ | ❌ | ✅ | ✅ | ✅ |
| async | ❌ | ✅ | ✅ | ❌ | ✅ |
| websocket | ❌ | ✅ | ❌ | ❌ | ✅ |
| fingerprints | ❌ | ❌ | ❌ | ❌ | ✅ |
| speed | 🐇 | 🐇🐇 | 🐇 | 🐇🐇 | 🐇🐇 |
Install[¶](https://curl-cffi.readthedocs.io/en/v0.8.0/#install "Link to this heading")
---------------------------------------------------------------------------------------
pip install curl\_cffi \--upgrade
For more details, see [Install](https://curl-cffi.readthedocs.io/en/v0.8.0/install.html)
.
Basic Usage[¶](https://curl-cffi.readthedocs.io/en/v0.8.0/#basic-usage "Link to this heading")
-----------------------------------------------------------------------------------------------
### requests-like[¶](https://curl-cffi.readthedocs.io/en/v0.8.0/#requests-like "Link to this heading")
from curl\_cffi import requests
url \= "https://tools.scrapfly.io/api/fp/ja3"
\# Notice the impersonate parameter
r \= requests.get("https://tools.scrapfly.io/api/fp/ja3", impersonate\="chrome110")
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 \= requests.get("https://tools.scrapfly.io/api/fp/ja3", impersonate\="chrome")
\# http/socks proxies are supported
proxies \= {"https": "http://localhost:3128"}
r \= requests.get("https://tools.scrapfly.io/api/fp/ja3", impersonate\="chrome110", proxies\=proxies)
proxies \= {"https": "socks://localhost:3128"}
r \= requests.get("https://tools.scrapfly.io/api/fp/ja3", impersonate\="chrome110", proxies\=proxies)
### Sessions[¶](https://curl-cffi.readthedocs.io/en/v0.8.0/#sessions "Link to this heading")
s \= requests.Session()
\# httpbin is a http test website
s.get("https://httpbin.org/cookies/set/foo/bar")
print(s.cookies)
\# \]>
r \= s.get("https://httpbin.org/cookies")
print(r.json())
\# {'cookies': {'foo': 'bar'}}
### asyncio[¶](https://curl-cffi.readthedocs.io/en/v0.8.0/#asyncio "Link to this heading")
from curl\_cffi.requests import AsyncSession
async with AsyncSession() as s:
r \= await s.get("https://example.com")
More concurrency:
import asyncio
from curl\_cffi.requests 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)
### WebSockets[¶](https://curl-cffi.readthedocs.io/en/v0.8.0/#websockets "Link to this heading")
from curl\_cffi.requests import Session, WebSocket
def on\_message(ws: WebSocket, message):
print(message)
with Session() as s:
ws \= s.ws\_connect(
"wss://api.gemini.com/v1/marketdata/BTCUSD",
on\_message\=on\_message,
)
ws.run\_forever()
Sponsor[¶](https://curl-cffi.readthedocs.io/en/v0.8.0/#sponsor "Link to this heading")
---------------------------------------------------------------------------------------
Click [here](https://buymeacoffee.com/yifei)
to buy me a coffee.
### Bypass Cloudflare with API[¶](https://curl-cffi.readthedocs.io/en/v0.8.0/#bypass-cloudflare-with-api "Link to this heading")
[](https://yescaptcha.com/i/stfnIO)
[Yescaptcha](https://yescaptcha.com/i/stfnIO)
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.
### ScrapeNinja[¶](https://curl-cffi.readthedocs.io/en/v0.8.0/#scrapeninja "Link to this heading")
[](https://scrapeninja.net/?utm_source=github&utm_medium=banner&utm_campaign=cffi)
[ScrapeNinja](https://scrapeninja.net/?utm_source=github&utm_medium=banner&utm_campaign=cffi)
is a web scraping API with two engines: fast, with high performance and TLS fingerprint; and slower with a real browser under the hood.
ScrapeNinja handles headless browsers, proxies, timeouts, retries, and helps with data extraction, so you can just get the data in JSON. Rotating proxies are available out of the box on all subscription plans.
Indices and tables[¶](https://curl-cffi.readthedocs.io/en/v0.8.0/#indices-and-tables "Link to this heading")
=============================================================================================================
* [Index](https://curl-cffi.readthedocs.io/en/v0.8.0/genindex.html)
* [Module Index](https://curl-cffi.readthedocs.io/en/v0.8.0/py-modindex.html)
* [Search Page](https://curl-cffi.readthedocs.io/en/v0.8.0/search.html)
[curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.8.0/#)
===========================================================
### Navigation
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.8.0/install.html)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.8.0/impersonate.html)
* [Cookies](https://curl-cffi.readthedocs.io/en/v0.8.0/cookies.html)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.8.0/advanced.html)
* [Exceptions](https://curl-cffi.readthedocs.io/en/v0.8.0/exceptions.html)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.8.0/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.8.0/faq.html)
* [API References](https://curl-cffi.readthedocs.io/en/v0.8.0/api.html)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.8.0/changelog.html)
### Related Topics
* [Documentation overview](https://curl-cffi.readthedocs.io/en/v0.8.0/#)
* Next: [Install](https://curl-cffi.readthedocs.io/en/v0.8.0/install.html "next chapter")
---
# Welcome to curl_cffi’s documentation! — curl_cffi documentation
Welcome to curl\_cffi’s documentation
===================================================================================================================================================
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.6.1/install.html)
* [Via pip](https://curl-cffi.readthedocs.io/en/v0.6.1/install.html#via-pip)
* [Beta versions](https://curl-cffi.readthedocs.io/en/v0.6.1/install.html#beta-versions)
* [Latest](https://curl-cffi.readthedocs.io/en/v0.6.1/install.html#latest)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.6.1/impersonate.html)
* [Supported browser versions](https://curl-cffi.readthedocs.io/en/v0.6.1/impersonate.html#supported-browser-versions)
* [Which version to use?](https://curl-cffi.readthedocs.io/en/v0.6.1/impersonate.html#which-version-to-use)
* [How to customize my fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.6.1/impersonate.html#how-to-customize-my-fingerprints-e-g-okhttp)
* [Should I randomize my fingerprints for each request?](https://curl-cffi.readthedocs.io/en/v0.6.1/impersonate.html#should-i-randomize-my-fingerprints-for-each-request)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.6.1/advanced.html)
* [low-level curl API](https://curl-cffi.readthedocs.io/en/v0.6.1/advanced.html#low-level-curl-api)
* [scrapy integrations](https://curl-cffi.readthedocs.io/en/v0.6.1/advanced.html#scrapy-integrations)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.6.1/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.6.1/faq.html)
* [Why does the JA3 fingerprints change for Chrome 110+ impersonation?](https://curl-cffi.readthedocs.io/en/v0.6.1/faq.html#why-does-the-ja3-fingerprints-change-for-chrome-110-impersonation)
* [I’m getting certs errors](https://curl-cffi.readthedocs.io/en/v0.6.1/faq.html#i-m-getting-certs-errors)
* [curl\_cffi.CurlError: Failed to perform, ErrCode: 92, Reason: ‘HTTP/2 stream 0 was not closed cleanly: PROTOCOL\_ERROR (err 1)’](https://curl-cffi.readthedocs.io/en/v0.6.1/faq.html#curl-cffi-curlerror-failed-to-perform-errcode-92-reason-http-2-stream-0-was-not-closed-cleanly-protocol-error-err-1)
* [API References](https://curl-cffi.readthedocs.io/en/v0.6.1/api.html)
* [curl low levl APIs](https://curl-cffi.readthedocs.io/en/v0.6.1/api.html#curl-low-levl-apis)
* [requests API](https://curl-cffi.readthedocs.io/en/v0.6.1/api.html#requests-api)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.6.1/changelog.html)
* [v0.6](https://curl-cffi.readthedocs.io/en/v0.6.1/changelog.html#v0-6)
* [v0.5](https://curl-cffi.readthedocs.io/en/v0.6.1/changelog.html#v0-5)
* [v0.4](https://curl-cffi.readthedocs.io/en/v0.6.1/changelog.html#v0-4)
* [v0.3](https://curl-cffi.readthedocs.io/en/v0.6.1/changelog.html#v0-3)
[中文 README](https://github.com/yifeikong/curl_cffi/blob/main/README-zh.md)
| [Discuss on Telegram](https://t.me/+lL9n33eZp480MGM1)
curl\_cffi is a Python binding for [curl-impersonate](https://github.com/yifeikong/curl-impersonate)
via [cffi](https://cffi.readthedocs.io/en/latest/)
.
Unlike other pure Python http clients like `httpx` or `requests`, `curl_cffi` can impersonate browsers’ TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try.
Features[¶](https://curl-cffi.readthedocs.io/en/v0.6.1/#features "Link to this heading")
-----------------------------------------------------------------------------------------
* Supports JA3/TLS and http2 fingerprints impersonation.
* Much faster than requests/httpx, on par with aiohttp/pycurl, see [benchmarks](https://github.com/yifeikong/curl_cffi/tree/main/benchmark)
.
* Mimics 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 websocket.
| | | | | | |
| --- | --- | --- | --- | --- | --- |Feature matrix[¶](https://curl-cffi.readthedocs.io/en/v0.6.1/#id4 "Link to this table")
| | requests | aiohttp | httpx | pycurl | curl\_cffi |
| --- | --- | --- | --- | --- | --- |
| http2 | ❌ | ❌ | ✅ | ✅ | ✅ |
| sync | ✅ | ❌ | ✅ | ✅ | ✅ |
| async | ❌ | ✅ | ✅ | ❌ | ✅ |
| websocket | ❌ | ✅ | ❌ | ❌ | ✅ |
| fingerprints | ❌ | ❌ | ❌ | ❌ | ✅ |
| speed | 🐇 | 🐇🐇 | 🐇 | 🐇🐇 | 🐇🐇 |
Install[¶](https://curl-cffi.readthedocs.io/en/v0.6.1/#install "Link to this heading")
---------------------------------------------------------------------------------------
pip install curl\_cffi \--upgrade
For more details, see [Install](https://curl-cffi.readthedocs.io/en/v0.6.1/install.html)
.
Basic Usage[¶](https://curl-cffi.readthedocs.io/en/v0.6.1/#basic-usage "Link to this heading")
-----------------------------------------------------------------------------------------------
### requests-like[¶](https://curl-cffi.readthedocs.io/en/v0.6.1/#requests-like "Link to this heading")
from curl\_cffi import requests
url \= "https://tls.browserleaks.com/json"
\# Notice the impersonate parameter
r \= requests.get(url, impersonate\="chrome")
print(r.json())
\# output: {..., "ja3n\_hash": "aa56c057ad164ec4fdcb7a5a283be9fc", ...}
\# the js3n fingerprint should be the same as target browser
\# http/socks proxies are supported
proxies \= {"https": "http://localhost:3128"}
r \= requests.get(url, impersonate\="chrome", proxies\=proxies)
proxies \= {"https": "socks://localhost:3128"}
r \= requests.get(url, impersonate\="chrome", proxies\=proxies)
### Sessions[¶](https://curl-cffi.readthedocs.io/en/v0.6.1/#sessions "Link to this heading")
s \= requests.Session()
\# httpbin is a http test website
s.get("https://httpbin.org/cookies/set/foo/bar")
print(s.cookies)
\# \]>
r \= s.get("https://httpbin.org/cookies")
print(r.json())
\# {'cookies': {'foo': 'bar'}}
### asyncio[¶](https://curl-cffi.readthedocs.io/en/v0.6.1/#asyncio "Link to this heading")
from curl\_cffi.requests import AsyncSession
async with AsyncSession() as s:
r \= await s.get("https://example.com")
More concurrency:
import asyncio
from curl\_cffi.requests 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)
### WebSockets[¶](https://curl-cffi.readthedocs.io/en/v0.6.1/#websockets "Link to this heading")
from curl\_cffi.requests import Session, WebSocket
def on\_message(ws: WebSocket, message):
print(message)
with Session() as s:
ws \= s.ws\_connect(
"wss://api.gemini.com/v1/marketdata/BTCUSD",
on\_message\=on\_message,
)
ws.run\_forever()
Sponsor[¶](https://curl-cffi.readthedocs.io/en/v0.6.1/#sponsor "Link to this heading")
---------------------------------------------------------------------------------------
Click [here](https://buymeacoffee.com/yifei)
to buy me a coffee.
### Bypass Cloudflare with API[¶](https://curl-cffi.readthedocs.io/en/v0.6.1/#bypass-cloudflare-with-api "Link to this heading")
[](https://raw.githubusercontent.com/yifeikong/curl_cffi/main/assets/yescaptcha.png)
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.
### ScrapeNinja[¶](https://curl-cffi.readthedocs.io/en/v0.6.1/#scrapeninja "Link to this heading")
[](https://scrapeninja.net/?utm_source=github&utm_medium=banner&utm_campaign=cffi)
[\`](https://curl-cffi.readthedocs.io/en/v0.6.1/#id2)
ScrapeNinja <[https://scrapeninja.net/?utm\_source=github&utm\_medium=banner&utm\_campaign=cffi](https://scrapeninja.net/?utm_source=github&utm_medium=banner&utm_campaign=cffi)
\>\_ is a web scraping API with two engines: fast, with high performance and TLS fingerprint; and slower with a real browser under the hood.
ScrapeNinja handles headless browsers, proxies, timeouts, retries, and helps with data extraction, so you can just get the data in JSON. Rotating proxies are available out of the box on all subscription plans.
Indices and tables[¶](https://curl-cffi.readthedocs.io/en/v0.6.1/#indices-and-tables "Link to this heading")
=============================================================================================================
* [Index](https://curl-cffi.readthedocs.io/en/v0.6.1/genindex.html)
* [Module Index](https://curl-cffi.readthedocs.io/en/v0.6.1/py-modindex.html)
* [Search Page](https://curl-cffi.readthedocs.io/en/v0.6.1/search.html)
[curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.6.1/#)
===========================================================
### Navigation
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.6.1/install.html)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.6.1/impersonate.html)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.6.1/advanced.html)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.6.1/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.6.1/faq.html)
* [API References](https://curl-cffi.readthedocs.io/en/v0.6.1/api.html)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.6.1/changelog.html)
### Related Topics
* [Documentation overview](https://curl-cffi.readthedocs.io/en/v0.6.1/#)
* Next: [Install](https://curl-cffi.readthedocs.io/en/v0.6.1/install.html "next chapter")
### Quick search
---
# Welcome to curl_cffi’s documentation! — curl_cffi documentation
Welcome to curl\_cffi’s documentation
===================================================================================================================================================
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.6.2/install.html)
* [Via pip](https://curl-cffi.readthedocs.io/en/v0.6.2/install.html#via-pip)
* [Beta versions](https://curl-cffi.readthedocs.io/en/v0.6.2/install.html#beta-versions)
* [Latest](https://curl-cffi.readthedocs.io/en/v0.6.2/install.html#latest)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.6.2/impersonate.html)
* [Supported browser versions](https://curl-cffi.readthedocs.io/en/v0.6.2/impersonate.html#supported-browser-versions)
* [Which version to use?](https://curl-cffi.readthedocs.io/en/v0.6.2/impersonate.html#which-version-to-use)
* [How to customize my fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.6.2/impersonate.html#how-to-customize-my-fingerprints-e-g-okhttp)
* [Should I randomize my fingerprints for each request?](https://curl-cffi.readthedocs.io/en/v0.6.2/impersonate.html#should-i-randomize-my-fingerprints-for-each-request)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.6.2/advanced.html)
* [low-level curl API](https://curl-cffi.readthedocs.io/en/v0.6.2/advanced.html#low-level-curl-api)
* [scrapy integrations](https://curl-cffi.readthedocs.io/en/v0.6.2/advanced.html#scrapy-integrations)
* [Using with eventlet/gevent](https://curl-cffi.readthedocs.io/en/v0.6.2/advanced.html#using-with-eventlet-gevent)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.6.2/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.6.2/faq.html)
* [Why does the JA3 fingerprints change for Chrome 110+ impersonation?](https://curl-cffi.readthedocs.io/en/v0.6.2/faq.html#why-does-the-ja3-fingerprints-change-for-chrome-110-impersonation)
* [Can I bypass Cloudflare with this project? or any other specific site.](https://curl-cffi.readthedocs.io/en/v0.6.2/faq.html#can-i-bypass-cloudflare-with-this-project-or-any-other-specific-site)
* [I’m getting certs errors](https://curl-cffi.readthedocs.io/en/v0.6.2/faq.html#i-m-getting-certs-errors)
* [ErrCode: 77, Reason: error setting certificate verify locations](https://curl-cffi.readthedocs.io/en/v0.6.2/faq.html#errcode-77-reason-error-setting-certificate-verify-locations)
* [How to use with fiddler/charles to intercept content](https://curl-cffi.readthedocs.io/en/v0.6.2/faq.html#how-to-use-with-fiddler-charles-to-intercept-content)
* [ErrCode: 92, Reason: ‘HTTP/2 stream 0 was not closed cleanly: PROTOCOL\_ERROR (err 1)’](https://curl-cffi.readthedocs.io/en/v0.6.2/faq.html#errcode-92-reason-http-2-stream-0-was-not-closed-cleanly-protocol-error-err-1)
* [Packaging with PyInstaller](https://curl-cffi.readthedocs.io/en/v0.6.2/faq.html#packaging-with-pyinstaller)
* [How to set proxy?](https://curl-cffi.readthedocs.io/en/v0.6.2/faq.html#how-to-set-proxy)
* [How to change the order of headers?](https://curl-cffi.readthedocs.io/en/v0.6.2/faq.html#how-to-change-the-order-of-headers)
* [API References](https://curl-cffi.readthedocs.io/en/v0.6.2/api.html)
* [curl low levl APIs](https://curl-cffi.readthedocs.io/en/v0.6.2/api.html#curl-low-levl-apis)
* [requests API](https://curl-cffi.readthedocs.io/en/v0.6.2/api.html#requests-api)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.6.2/changelog.html)
* [v0.6](https://curl-cffi.readthedocs.io/en/v0.6.2/changelog.html#v0-6)
* [v0.5](https://curl-cffi.readthedocs.io/en/v0.6.2/changelog.html#v0-5)
* [v0.4](https://curl-cffi.readthedocs.io/en/v0.6.2/changelog.html#v0-4)
* [v0.3](https://curl-cffi.readthedocs.io/en/v0.6.2/changelog.html#v0-3)
[中文 README](https://github.com/yifeikong/curl_cffi/blob/main/README-zh.md)
| [Discuss on Telegram](https://t.me/+lL9n33eZp480MGM1)
curl\_cffi is a Python binding for [curl-impersonate](https://github.com/yifeikong/curl-impersonate)
via [cffi](https://cffi.readthedocs.io/en/latest/)
.
Unlike other pure Python http clients like `httpx` or `requests`, `curl_cffi` can impersonate browsers’ TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try.
Features[¶](https://curl-cffi.readthedocs.io/en/v0.6.2/#features "Link to this heading")
-----------------------------------------------------------------------------------------
* Supports JA3/TLS and http2 fingerprints impersonation.
* Much faster than requests/httpx, on par with aiohttp/pycurl, see [benchmarks](https://github.com/yifeikong/curl_cffi/tree/main/benchmark)
.
* Mimics 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 websocket.
| | | | | | |
| --- | --- | --- | --- | --- | --- |Feature matrix[¶](https://curl-cffi.readthedocs.io/en/v0.6.2/#id3 "Link to this table")
| | requests | aiohttp | httpx | pycurl | curl\_cffi |
| --- | --- | --- | --- | --- | --- |
| http2 | ❌ | ❌ | ✅ | ✅ | ✅ |
| sync | ✅ | ❌ | ✅ | ✅ | ✅ |
| async | ❌ | ✅ | ✅ | ❌ | ✅ |
| websocket | ❌ | ✅ | ❌ | ❌ | ✅ |
| fingerprints | ❌ | ❌ | ❌ | ❌ | ✅ |
| speed | 🐇 | 🐇🐇 | 🐇 | 🐇🐇 | 🐇🐇 |
Install[¶](https://curl-cffi.readthedocs.io/en/v0.6.2/#install "Link to this heading")
---------------------------------------------------------------------------------------
pip install curl\_cffi \--upgrade
For more details, see [Install](https://curl-cffi.readthedocs.io/en/v0.6.2/install.html)
.
Basic Usage[¶](https://curl-cffi.readthedocs.io/en/v0.6.2/#basic-usage "Link to this heading")
-----------------------------------------------------------------------------------------------
### requests-like[¶](https://curl-cffi.readthedocs.io/en/v0.6.2/#requests-like "Link to this heading")
from curl\_cffi import requests
url \= "https://tls.browserleaks.com/json"
\# Notice the impersonate parameter
r \= requests.get(url, impersonate\="chrome")
print(r.json())
\# output: {..., "ja3n\_hash": "aa56c057ad164ec4fdcb7a5a283be9fc", ...}
\# the js3n fingerprint should be the same as target browser
\# http/socks proxies are supported
proxies \= {"https": "http://localhost:3128"}
r \= requests.get(url, impersonate\="chrome", proxies\=proxies)
proxies \= {"https": "socks://localhost:3128"}
r \= requests.get(url, impersonate\="chrome", proxies\=proxies)
### Sessions[¶](https://curl-cffi.readthedocs.io/en/v0.6.2/#sessions "Link to this heading")
s \= requests.Session()
\# httpbin is a http test website
s.get("https://httpbin.org/cookies/set/foo/bar")
print(s.cookies)
\# \]>
r \= s.get("https://httpbin.org/cookies")
print(r.json())
\# {'cookies': {'foo': 'bar'}}
### asyncio[¶](https://curl-cffi.readthedocs.io/en/v0.6.2/#asyncio "Link to this heading")
from curl\_cffi.requests import AsyncSession
async with AsyncSession() as s:
r \= await s.get("https://example.com")
More concurrency:
import asyncio
from curl\_cffi.requests 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)
### WebSockets[¶](https://curl-cffi.readthedocs.io/en/v0.6.2/#websockets "Link to this heading")
from curl\_cffi.requests import Session, WebSocket
def on\_message(ws: WebSocket, message):
print(message)
with Session() as s:
ws \= s.ws\_connect(
"wss://api.gemini.com/v1/marketdata/BTCUSD",
on\_message\=on\_message,
)
ws.run\_forever()
Sponsor[¶](https://curl-cffi.readthedocs.io/en/v0.6.2/#sponsor "Link to this heading")
---------------------------------------------------------------------------------------
Click [here](https://buymeacoffee.com/yifei)
to buy me a coffee.
### Bypass Cloudflare with API[¶](https://curl-cffi.readthedocs.io/en/v0.6.2/#bypass-cloudflare-with-api "Link to this heading")
[](https://yescaptcha.com/i/stfnIO)
[Yescaptcha](https://yescaptcha.com/i/stfnIO)
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.
### ScrapeNinja[¶](https://curl-cffi.readthedocs.io/en/v0.6.2/#scrapeninja "Link to this heading")
[](https://scrapeninja.net/?utm_source=github&utm_medium=banner&utm_campaign=cffi)
[ScrapeNinja](https://scrapeninja.net/?utm_source=github&utm_medium=banner&utm_campaign=cffi)
is a web scraping API with two engines: fast, with high performance and TLS fingerprint; and slower with a real browser under the hood.
ScrapeNinja handles headless browsers, proxies, timeouts, retries, and helps with data extraction, so you can just get the data in JSON. Rotating proxies are available out of the box on all subscription plans.
Indices and tables[¶](https://curl-cffi.readthedocs.io/en/v0.6.2/#indices-and-tables "Link to this heading")
=============================================================================================================
* [Index](https://curl-cffi.readthedocs.io/en/v0.6.2/genindex.html)
* [Module Index](https://curl-cffi.readthedocs.io/en/v0.6.2/py-modindex.html)
* [Search Page](https://curl-cffi.readthedocs.io/en/v0.6.2/search.html)
[curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.6.2/#)
===========================================================
### Navigation
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.6.2/install.html)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.6.2/impersonate.html)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.6.2/advanced.html)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.6.2/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.6.2/faq.html)
* [API References](https://curl-cffi.readthedocs.io/en/v0.6.2/api.html)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.6.2/changelog.html)
### Related Topics
* [Documentation overview](https://curl-cffi.readthedocs.io/en/v0.6.2/#)
* Next: [Install](https://curl-cffi.readthedocs.io/en/v0.6.2/install.html "next chapter")
### Quick search
---
# Welcome to curl_cffi’s documentation! — curl_cffi documentation
Welcome to curl\_cffi’s documentation
===================================================================================================================================================
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.6.0/install.html)
* [Via pip](https://curl-cffi.readthedocs.io/en/v0.6.0/install.html#via-pip)
* [Beta versions](https://curl-cffi.readthedocs.io/en/v0.6.0/install.html#beta-versions)
* [Latest](https://curl-cffi.readthedocs.io/en/v0.6.0/install.html#latest)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.6.0/impersonate.html)
* [Supported browser versions](https://curl-cffi.readthedocs.io/en/v0.6.0/impersonate.html#supported-browser-versions)
* [Which version to use?](https://curl-cffi.readthedocs.io/en/v0.6.0/impersonate.html#which-version-to-use)
* [How to customize my fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.6.0/impersonate.html#how-to-customize-my-fingerprints-e-g-okhttp)
* [Should I randomize my fingerprints for each request?](https://curl-cffi.readthedocs.io/en/v0.6.0/impersonate.html#should-i-randomize-my-fingerprints-for-each-request)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.6.0/advanced.html)
* [low-level curl API](https://curl-cffi.readthedocs.io/en/v0.6.0/advanced.html#low-level-curl-api)
* [scrapy integrations](https://curl-cffi.readthedocs.io/en/v0.6.0/advanced.html#scrapy-integrations)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.6.0/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.6.0/faq.html)
* [Why does the JA3 fingerprints change for Chrome 110+ impersonation?](https://curl-cffi.readthedocs.io/en/v0.6.0/faq.html#why-does-the-ja3-fingerprints-change-for-chrome-110-impersonation)
* [I’m getting certs errors](https://curl-cffi.readthedocs.io/en/v0.6.0/faq.html#i-m-getting-certs-errors)
* [curl\_cffi.CurlError: Failed to perform, ErrCode: 92, Reason: ‘HTTP/2 stream 0 was not closed cleanly: PROTOCOL\_ERROR (err 1)’](https://curl-cffi.readthedocs.io/en/v0.6.0/faq.html#curl-cffi-curlerror-failed-to-perform-errcode-92-reason-http-2-stream-0-was-not-closed-cleanly-protocol-error-err-1)
* [API References](https://curl-cffi.readthedocs.io/en/v0.6.0/api.html)
* [curl low levl APIs](https://curl-cffi.readthedocs.io/en/v0.6.0/api.html#curl-low-levl-apis)
* [requests API](https://curl-cffi.readthedocs.io/en/v0.6.0/api.html#requests-api)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.6.0/changelog.html)
* [v0.6](https://curl-cffi.readthedocs.io/en/v0.6.0/changelog.html#v0-6)
* [v0.5](https://curl-cffi.readthedocs.io/en/v0.6.0/changelog.html#v0-5)
* [v0.4](https://curl-cffi.readthedocs.io/en/v0.6.0/changelog.html#v0-4)
* [v0.3](https://curl-cffi.readthedocs.io/en/v0.6.0/changelog.html#v0-3)
[中文 README](https://github.com/yifeikong/curl_cffi/blob/main/README-zh.md)
| [Discuss on Telegram](https://t.me/+lL9n33eZp480MGM1)
curl\_cffi is a Python binding for [curl-impersonate](https://github.com/yifeikong/curl-impersonate)
via [cffi](https://cffi.readthedocs.io/en/latest/)
.
Unlike other pure Python http clients like `httpx` or `requests`, `curl_cffi` can impersonate browsers’ TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try.
Features[¶](https://curl-cffi.readthedocs.io/en/v0.6.0/#features "Link to this heading")
-----------------------------------------------------------------------------------------
* Supports JA3/TLS and http2 fingerprints impersonation.
* Much faster than requests/httpx, on par with aiohttp/pycurl, see [benchmarks](https://github.com/yifeikong/curl_cffi/tree/main/benchmark)
.
* Mimics 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 websocket.
| | | | | | |
| --- | --- | --- | --- | --- | --- |Feature matrix[¶](https://curl-cffi.readthedocs.io/en/v0.6.0/#id2 "Link to this table")
| | requests | aiohttp | httpx | pycurl | curl\_cffi |
| --- | --- | --- | --- | --- | --- |
| http2 | ❌ | ❌ | ✅ | ✅ | ✅ |
| sync | ✅ | ❌ | ✅ | ✅ | ✅ |
| async | ❌ | ✅ | ✅ | ❌ | ✅ |
| websocket | ❌ | ✅ | ❌ | ❌ | ✅ |
| fingerprints | ❌ | ❌ | ❌ | ❌ | ✅ |
| speed | 🐇 | 🐇🐇 | 🐇 | 🐇🐇 | 🐇🐇 |
Install[¶](https://curl-cffi.readthedocs.io/en/v0.6.0/#install "Link to this heading")
---------------------------------------------------------------------------------------
pip install curl\_cffi \--upgrade
For more details, see [Install](https://curl-cffi.readthedocs.io/en/v0.6.0/install.html)
.
Basic Usage[¶](https://curl-cffi.readthedocs.io/en/v0.6.0/#basic-usage "Link to this heading")
-----------------------------------------------------------------------------------------------
### requests-like[¶](https://curl-cffi.readthedocs.io/en/v0.6.0/#requests-like "Link to this heading")
from curl\_cffi import requests
url \= "https://tls.browserleaks.com/json"
\# Notice the impersonate parameter
r \= requests.get(url, impersonate\="chrome")
print(r.json())
\# output: {..., "ja3n\_hash": "aa56c057ad164ec4fdcb7a5a283be9fc", ...}
\# the js3n fingerprint should be the same as target browser
\# http/socks proxies are supported
proxies \= {"https": "http://localhost:3128"}
r \= requests.get(url, impersonate\="chrome", proxies\=proxies)
proxies \= {"https": "socks://localhost:3128"}
r \= requests.get(url, impersonate\="chrome", proxies\=proxies)
### Sessions[¶](https://curl-cffi.readthedocs.io/en/v0.6.0/#sessions "Link to this heading")
s \= requests.Session()
\# httpbin is a http test website
s.get("https://httpbin.org/cookies/set/foo/bar")
print(s.cookies)
\# \]>
r \= s.get("https://httpbin.org/cookies")
print(r.json())
\# {'cookies': {'foo': 'bar'}}
### asyncio[¶](https://curl-cffi.readthedocs.io/en/v0.6.0/#asyncio "Link to this heading")
from curl\_cffi.requests import AsyncSession
async with AsyncSession() as s:
r \= await s.get("https://example.com")
More concurrency:
import asyncio
from curl\_cffi.requests 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)
### WebSockets[¶](https://curl-cffi.readthedocs.io/en/v0.6.0/#websockets "Link to this heading")
from curl\_cffi.requests import Session, WebSocket
def on\_message(ws: WebSocket, message):
print(message)
with Session() as s:
ws \= s.ws\_connect(
"wss://api.gemini.com/v1/marketdata/BTCUSD",
on\_message\=on\_message,
)
ws.run\_forever()
Sponsor[¶](https://curl-cffi.readthedocs.io/en/v0.6.0/#sponsor "Link to this heading")
---------------------------------------------------------------------------------------
Click [here](https://buymeacoffee.com/yifei)
to buy me a coffee.
### Bypass Cloudflare with API[¶](https://curl-cffi.readthedocs.io/en/v0.6.0/#bypass-cloudflare-with-api "Link to this heading")
[](https://raw.githubusercontent.com/yifeikong/curl_cffi/main/assets/yescaptcha.png)
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.
### ScrapeNinja[¶](https://curl-cffi.readthedocs.io/en/v0.6.0/#scrapeninja "Link to this heading")
[](https://scrapeninja.net/img/logo_with_text_new5.svg)
ScrapeNinja is a web scraping API with two engines: fast, with high performance and TLS fingerprint; and slower with a real browser under the hood.
ScrapeNinja handles headless browsers, proxies, timeouts, retries, and helps with data extraction, so you can just get the data in JSON. Rotating proxies are available out of the box on all subscription plans.
Indices and tables[¶](https://curl-cffi.readthedocs.io/en/v0.6.0/#indices-and-tables "Link to this heading")
=============================================================================================================
* [Index](https://curl-cffi.readthedocs.io/en/v0.6.0/genindex.html)
* [Module Index](https://curl-cffi.readthedocs.io/en/v0.6.0/py-modindex.html)
* [Search Page](https://curl-cffi.readthedocs.io/en/v0.6.0/search.html)
[curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.6.0/#)
===========================================================
### Navigation
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.6.0/install.html)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.6.0/impersonate.html)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.6.0/advanced.html)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.6.0/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.6.0/faq.html)
* [API References](https://curl-cffi.readthedocs.io/en/v0.6.0/api.html)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.6.0/changelog.html)
### Related Topics
* [Documentation overview](https://curl-cffi.readthedocs.io/en/v0.6.0/#)
* Next: [Install](https://curl-cffi.readthedocs.io/en/v0.6.0/install.html "next chapter")
### Quick search
---
# Welcome to curl_cffi’s documentation! — curl_cffi documentation
Welcome to curl\_cffi’s documentation
===================================================================================================================================================
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.6.4/install.html)
* [Via pip](https://curl-cffi.readthedocs.io/en/v0.6.4/install.html#via-pip)
* [Beta versions](https://curl-cffi.readthedocs.io/en/v0.6.4/install.html#beta-versions)
* [Latest](https://curl-cffi.readthedocs.io/en/v0.6.4/install.html#latest)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.6.4/impersonate.html)
* [Supported browser versions](https://curl-cffi.readthedocs.io/en/v0.6.4/impersonate.html#supported-browser-versions)
* [Which version to use?](https://curl-cffi.readthedocs.io/en/v0.6.4/impersonate.html#which-version-to-use)
* [How to customize my fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.6.4/impersonate.html#how-to-customize-my-fingerprints-e-g-okhttp)
* [Should I randomize my fingerprints for each request?](https://curl-cffi.readthedocs.io/en/v0.6.4/impersonate.html#should-i-randomize-my-fingerprints-for-each-request)
* [Can I change JS fingerprints with this library?](https://curl-cffi.readthedocs.io/en/v0.6.4/impersonate.html#can-i-change-js-fingerprints-with-this-library)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.6.4/advanced.html)
* [low-level curl API](https://curl-cffi.readthedocs.io/en/v0.6.4/advanced.html#low-level-curl-api)
* [scrapy integrations](https://curl-cffi.readthedocs.io/en/v0.6.4/advanced.html#scrapy-integrations)
* [Using with eventlet/gevent](https://curl-cffi.readthedocs.io/en/v0.6.4/advanced.html#using-with-eventlet-gevent)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.6.4/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.6.4/faq.html)
* [Why does the JA3 fingerprints change for Chrome 110+ impersonation?](https://curl-cffi.readthedocs.io/en/v0.6.4/faq.html#why-does-the-ja3-fingerprints-change-for-chrome-110-impersonation)
* [Can I bypass Cloudflare with this project? or any other specific site.](https://curl-cffi.readthedocs.io/en/v0.6.4/faq.html#can-i-bypass-cloudflare-with-this-project-or-any-other-specific-site)
* [I’m getting certs errors](https://curl-cffi.readthedocs.io/en/v0.6.4/faq.html#i-m-getting-certs-errors)
* [ErrCode: 77, Reason: error setting certificate verify locations](https://curl-cffi.readthedocs.io/en/v0.6.4/faq.html#errcode-77-reason-error-setting-certificate-verify-locations)
* [How to use with fiddler/charles to intercept content](https://curl-cffi.readthedocs.io/en/v0.6.4/faq.html#how-to-use-with-fiddler-charles-to-intercept-content)
* [ErrCode: 92, Reason: ‘HTTP/2 stream 0 was not closed cleanly: PROTOCOL\_ERROR (err 1)’](https://curl-cffi.readthedocs.io/en/v0.6.4/faq.html#errcode-92-reason-http-2-stream-0-was-not-closed-cleanly-protocol-error-err-1)
* [Packaging with PyInstaller](https://curl-cffi.readthedocs.io/en/v0.6.4/faq.html#packaging-with-pyinstaller)
* [How to set proxy?](https://curl-cffi.readthedocs.io/en/v0.6.4/faq.html#how-to-set-proxy)
* [How to change the order of headers?](https://curl-cffi.readthedocs.io/en/v0.6.4/faq.html#how-to-change-the-order-of-headers)
* [API References](https://curl-cffi.readthedocs.io/en/v0.6.4/api.html)
* [curl low levl APIs](https://curl-cffi.readthedocs.io/en/v0.6.4/api.html#curl-low-levl-apis)
* [requests API](https://curl-cffi.readthedocs.io/en/v0.6.4/api.html#requests-api)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.6.4/changelog.html)
* [v0.6](https://curl-cffi.readthedocs.io/en/v0.6.4/changelog.html#v0-6)
* [v0.5](https://curl-cffi.readthedocs.io/en/v0.6.4/changelog.html#v0-5)
* [v0.4](https://curl-cffi.readthedocs.io/en/v0.6.4/changelog.html#v0-4)
* [v0.3](https://curl-cffi.readthedocs.io/en/v0.6.4/changelog.html#v0-3)
[中文 README](https://github.com/yifeikong/curl_cffi/blob/main/README-zh.md)
| [Discuss on Telegram](https://t.me/+lL9n33eZp480MGM1)
curl\_cffi is a Python binding for [curl-impersonate](https://github.com/yifeikong/curl-impersonate)
via [cffi](https://cffi.readthedocs.io/en/latest/)
.
Unlike other pure Python http clients like `httpx` or `requests`, `curl_cffi` can impersonate browsers’ TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try.
* * *
[](https://scrapfly.io/?utm_source=github&utm_medium=sponsoring&utm_campaign=curl_cffi)
[Scrapfly](https://scrapfly.io/?utm_source=github&utm_medium=sponsoring&utm_campaign=curl_cffi)
is an enterprise-grade solution providing Web Scraping API that aims to simplify the scraping process by managing everything: real browser rendering, rotating proxies, and fingerprints (TLS, HTTP, browser) to bypass all major anti-bots. Scrapfly also unlocks the observability by providing an analytical dashboard and measuring the success rate/block rate in details.
Scrapfly is a good solution if you are looking for a cloud-managed solution for `curl_cffi`. If you are managing TLS/HTTP fingerprint by yourself with `curl_cffi`, they also maintain [this tool](https://scrapfly.io/web-scraping-tools/curl-python/curl_cffi)
to convert curl command into python curl\_cffi code!
* * *
Features[¶](https://curl-cffi.readthedocs.io/en/v0.6.4/#features "Link to this heading")
-----------------------------------------------------------------------------------------
* Supports JA3/TLS and http2 fingerprints impersonation.
* Much faster than requests/httpx, on par with aiohttp/pycurl, see [benchmarks](https://github.com/yifeikong/curl_cffi/tree/main/benchmark)
.
* Mimics 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 websocket.
| | | | | | |
| --- | --- | --- | --- | --- | --- |Feature matrix[¶](https://curl-cffi.readthedocs.io/en/v0.6.4/#id3 "Link to this table")
| | requests | aiohttp | httpx | pycurl | curl\_cffi |
| --- | --- | --- | --- | --- | --- |
| http2 | ❌ | ❌ | ✅ | ✅ | ✅ |
| sync | ✅ | ❌ | ✅ | ✅ | ✅ |
| async | ❌ | ✅ | ✅ | ❌ | ✅ |
| websocket | ❌ | ✅ | ❌ | ❌ | ✅ |
| fingerprints | ❌ | ❌ | ❌ | ❌ | ✅ |
| speed | 🐇 | 🐇🐇 | 🐇 | 🐇🐇 | 🐇🐇 |
Install[¶](https://curl-cffi.readthedocs.io/en/v0.6.4/#install "Link to this heading")
---------------------------------------------------------------------------------------
pip install curl\_cffi \--upgrade
For more details, see [Install](https://curl-cffi.readthedocs.io/en/v0.6.4/install.html)
.
Basic Usage[¶](https://curl-cffi.readthedocs.io/en/v0.6.4/#basic-usage "Link to this heading")
-----------------------------------------------------------------------------------------------
### requests-like[¶](https://curl-cffi.readthedocs.io/en/v0.6.4/#requests-like "Link to this heading")
from curl\_cffi import requests
url \= "https://tls.browserleaks.com/json"
\# Notice the impersonate parameter
r \= requests.get(url, impersonate\="chrome")
print(r.json())
\# output: {..., "ja3n\_hash": "aa56c057ad164ec4fdcb7a5a283be9fc", ...}
\# the js3n fingerprint should be the same as target browser
\# http/socks proxies are supported
proxies \= {"https": "http://localhost:3128"}
r \= requests.get(url, impersonate\="chrome", proxies\=proxies)
proxies \= {"https": "socks://localhost:3128"}
r \= requests.get(url, impersonate\="chrome", proxies\=proxies)
### Sessions[¶](https://curl-cffi.readthedocs.io/en/v0.6.4/#sessions "Link to this heading")
s \= requests.Session()
\# httpbin is a http test website
s.get("https://httpbin.org/cookies/set/foo/bar")
print(s.cookies)
\# \]>
r \= s.get("https://httpbin.org/cookies")
print(r.json())
\# {'cookies': {'foo': 'bar'}}
### asyncio[¶](https://curl-cffi.readthedocs.io/en/v0.6.4/#asyncio "Link to this heading")
from curl\_cffi.requests import AsyncSession
async with AsyncSession() as s:
r \= await s.get("https://example.com")
More concurrency:
import asyncio
from curl\_cffi.requests 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)
### WebSockets[¶](https://curl-cffi.readthedocs.io/en/v0.6.4/#websockets "Link to this heading")
from curl\_cffi.requests import Session, WebSocket
def on\_message(ws: WebSocket, message):
print(message)
with Session() as s:
ws \= s.ws\_connect(
"wss://api.gemini.com/v1/marketdata/BTCUSD",
on\_message\=on\_message,
)
ws.run\_forever()
Sponsor[¶](https://curl-cffi.readthedocs.io/en/v0.6.4/#sponsor "Link to this heading")
---------------------------------------------------------------------------------------
Click [here](https://buymeacoffee.com/yifei)
to buy me a coffee.
### Bypass Cloudflare with API[¶](https://curl-cffi.readthedocs.io/en/v0.6.4/#bypass-cloudflare-with-api "Link to this heading")
[](https://yescaptcha.com/i/stfnIO)
[Yescaptcha](https://yescaptcha.com/i/stfnIO)
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.
### ScrapeNinja[¶](https://curl-cffi.readthedocs.io/en/v0.6.4/#scrapeninja "Link to this heading")
[](https://scrapeninja.net/?utm_source=github&utm_medium=banner&utm_campaign=cffi)
[ScrapeNinja](https://scrapeninja.net/?utm_source=github&utm_medium=banner&utm_campaign=cffi)
is a web scraping API with two engines: fast, with high performance and TLS fingerprint; and slower with a real browser under the hood.
ScrapeNinja handles headless browsers, proxies, timeouts, retries, and helps with data extraction, so you can just get the data in JSON. Rotating proxies are available out of the box on all subscription plans.
Indices and tables[¶](https://curl-cffi.readthedocs.io/en/v0.6.4/#indices-and-tables "Link to this heading")
=============================================================================================================
* [Index](https://curl-cffi.readthedocs.io/en/v0.6.4/genindex.html)
* [Module Index](https://curl-cffi.readthedocs.io/en/v0.6.4/py-modindex.html)
* [Search Page](https://curl-cffi.readthedocs.io/en/v0.6.4/search.html)
[curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.6.4/#)
===========================================================
### Navigation
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.6.4/install.html)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.6.4/impersonate.html)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.6.4/advanced.html)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.6.4/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.6.4/faq.html)
* [API References](https://curl-cffi.readthedocs.io/en/v0.6.4/api.html)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.6.4/changelog.html)
### Related Topics
* [Documentation overview](https://curl-cffi.readthedocs.io/en/v0.6.4/#)
* Next: [Install](https://curl-cffi.readthedocs.io/en/v0.6.4/install.html "next chapter")
### Quick search
---
# Welcome to curl_cffi’s documentation! — curl_cffi documentation
Welcome to curl\_cffi’s documentation
===================================================================================================================================================
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.9.0/install.html)
* [Via pip](https://curl-cffi.readthedocs.io/en/v0.9.0/install.html#via-pip)
* [Beta versions](https://curl-cffi.readthedocs.io/en/v0.9.0/install.html#beta-versions)
* [Latest](https://curl-cffi.readthedocs.io/en/v0.9.0/install.html#latest)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.9.0/impersonate.html)
* [Supported browser versions](https://curl-cffi.readthedocs.io/en/v0.9.0/impersonate.html#supported-browser-versions)
* [Which version to use?](https://curl-cffi.readthedocs.io/en/v0.9.0/impersonate.html#which-version-to-use)
* [How to use my own fingerprints other than the builtin ones? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.9.0/impersonate.html#how-to-use-my-own-fingerprints-other-than-the-builtin-ones-e-g-okhttp)
* [Should I randomize my fingerprints for each request?](https://curl-cffi.readthedocs.io/en/v0.9.0/impersonate.html#should-i-randomize-my-fingerprints-for-each-request)
* [Can I change JavaScript fingerprints with this library?](https://curl-cffi.readthedocs.io/en/v0.9.0/impersonate.html#can-i-change-javascript-fingerprints-with-this-library)
* [Cookies](https://curl-cffi.readthedocs.io/en/v0.9.0/cookies.html)
* [How to save and load cookies](https://curl-cffi.readthedocs.io/en/v0.9.0/cookies.html#how-to-save-and-load-cookies)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.9.0/advanced.html)
* [Low-level curl API](https://curl-cffi.readthedocs.io/en/v0.9.0/advanced.html#low-level-curl-api)
* [Scrapy integrations](https://curl-cffi.readthedocs.io/en/v0.9.0/advanced.html#scrapy-integrations)
* [Using with eventlet/gevent](https://curl-cffi.readthedocs.io/en/v0.9.0/advanced.html#using-with-eventlet-gevent)
* [As a urllib3/requests adapter](https://curl-cffi.readthedocs.io/en/v0.9.0/advanced.html#as-a-urllib3-requests-adapter)
* [As a httpx transport](https://curl-cffi.readthedocs.io/en/v0.9.0/advanced.html#as-a-httpx-transport)
* [Exceptions](https://curl-cffi.readthedocs.io/en/v0.9.0/exceptions.html)
* [Exceptions](https://curl-cffi.readthedocs.io/en/v0.9.0/exceptions.html#id1)
* [Warnings](https://curl-cffi.readthedocs.io/en/v0.9.0/exceptions.html#warnings)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.9.0/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.9.0/faq.html)
* [Why does the JA3 fingerprints change for Chrome 110+ impersonation?](https://curl-cffi.readthedocs.io/en/v0.9.0/faq.html#why-does-the-ja3-fingerprints-change-for-chrome-110-impersonation)
* [Can I bypass Cloudflare with this project? or any other specific site.](https://curl-cffi.readthedocs.io/en/v0.9.0/faq.html#can-i-bypass-cloudflare-with-this-project-or-any-other-specific-site)
* [I’m getting certs errors](https://curl-cffi.readthedocs.io/en/v0.9.0/faq.html#i-m-getting-certs-errors)
* [ErrCode: 77, Reason: error setting certificate verify locations](https://curl-cffi.readthedocs.io/en/v0.9.0/faq.html#errcode-77-reason-error-setting-certificate-verify-locations)
* [How to use with fiddler/charles to intercept content](https://curl-cffi.readthedocs.io/en/v0.9.0/faq.html#how-to-use-with-fiddler-charles-to-intercept-content)
* [ErrCode: 92, Reason: ‘HTTP/2 stream 0 was not closed cleanly: PROTOCOL\_ERROR (err 1)’](https://curl-cffi.readthedocs.io/en/v0.9.0/faq.html#errcode-92-reason-http-2-stream-0-was-not-closed-cleanly-protocol-error-err-1)
* [Packaging with PyInstaller](https://curl-cffi.readthedocs.io/en/v0.9.0/faq.html#packaging-with-pyinstaller)
* [How to set proxy?](https://curl-cffi.readthedocs.io/en/v0.9.0/faq.html#how-to-set-proxy)
* [How to change the order of headers?](https://curl-cffi.readthedocs.io/en/v0.9.0/faq.html#how-to-change-the-order-of-headers)
* [API References](https://curl-cffi.readthedocs.io/en/v0.9.0/api.html)
* [curl low levl APIs](https://curl-cffi.readthedocs.io/en/v0.9.0/api.html#curl-low-levl-apis)
* [requests API](https://curl-cffi.readthedocs.io/en/v0.9.0/api.html#requests-api)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.9.0/changelog.html)
* [v0.9](https://curl-cffi.readthedocs.io/en/v0.9.0/changelog.html#v0-9)
* [v0.8](https://curl-cffi.readthedocs.io/en/v0.9.0/changelog.html#v0-8)
* [v0.7](https://curl-cffi.readthedocs.io/en/v0.9.0/changelog.html#v0-7)
* [v0.6](https://curl-cffi.readthedocs.io/en/v0.9.0/changelog.html#v0-6)
* [v0.5](https://curl-cffi.readthedocs.io/en/v0.9.0/changelog.html#v0-5)
* [v0.4](https://curl-cffi.readthedocs.io/en/v0.9.0/changelog.html#v0-4)
* [v0.3](https://curl-cffi.readthedocs.io/en/v0.9.0/changelog.html#v0-3)
[Discuss on Telegram](https://t.me/+lL9n33eZp480MGM1)
curl\_cffi is a Python binding for [\`curl-impersonate fork\`\_](https://curl-cffi.readthedocs.io/en/v0.9.0/#id4)
via [cffi](https://cffi.readthedocs.io/en/latest/)
.
Unlike other pure Python http clients like `httpx` or `requests`, `curl_cffi` can impersonate browsers’ TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try.
* * *
[](https://nubela.co/proxycurl/?utm_campaign=influencer_marketing&utm_source=github&utm_medium=social&utm_term=-&utm_content=lexiforest-curl_cffi)
Scrape public LinkedIn profile data at scale with [Proxycurl APIs](https://nubela.co/proxycurl/?utm_campaign=influencer_marketing&utm_source=github&utm_medium=social&utm_term=-&utm_content=lexiforest-curl_cffi)
. Built for developers, by developers.
* GDPR, CCPA, SOC2 compliant
* High rate limit (300 requests/min), Fast (APIs respond in ~2s), High accuracy
* Fresh data - 88% of data is scraped real-time, other 12% is <29 days
* Tons of data points returned per profile
* * *
Features[¶](https://curl-cffi.readthedocs.io/en/v0.9.0/#features "Link to this heading")
-----------------------------------------------------------------------------------------
* Supports JA3/TLS and http2 fingerprints impersonation.
* Much faster than requests/httpx, on par with aiohttp/pycurl, see [benchmarks](https://github.com/lexiforest/curl_cffi/tree/main/benchmark)
.
* Mimics 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 websocket.
| | | | | | |
| --- | --- | --- | --- | --- | --- |Feature matrix[¶](https://curl-cffi.readthedocs.io/en/v0.9.0/#id3 "Link to this table")
| | requests | aiohttp | httpx | pycurl | curl\_cffi |
| --- | --- | --- | --- | --- | --- |
| http2 | ❌ | ❌ | ✅ | ✅ | ✅ |
| sync | ✅ | ❌ | ✅ | ✅ | ✅ |
| async | ❌ | ✅ | ✅ | ❌ | ✅ |
| websocket | ❌ | ✅ | ❌ | ❌ | ✅ |
| fingerprints | ❌ | ❌ | ❌ | ❌ | ✅ |
| speed | 🐇 | 🐇🐇 | 🐇 | 🐇🐇 | 🐇🐇 |
Install[¶](https://curl-cffi.readthedocs.io/en/v0.9.0/#install "Link to this heading")
---------------------------------------------------------------------------------------
pip install curl\_cffi \--upgrade
For more details, see [Install](https://curl-cffi.readthedocs.io/en/v0.9.0/install.html)
.
Basic Usage[¶](https://curl-cffi.readthedocs.io/en/v0.9.0/#basic-usage "Link to this heading")
-----------------------------------------------------------------------------------------------
### requests-like[¶](https://curl-cffi.readthedocs.io/en/v0.9.0/#requests-like "Link to this heading")
from curl\_cffi import requests
url \= "https://tools.scrapfly.io/api/fp/ja3"
\# Notice the impersonate parameter
r \= requests.get("https://tools.scrapfly.io/api/fp/ja3", impersonate\="chrome110")
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 \= requests.get("https://tools.scrapfly.io/api/fp/ja3", impersonate\="chrome")
\# http/socks proxies are supported
proxies \= {"https": "http://localhost:3128"}
r \= requests.get("https://tools.scrapfly.io/api/fp/ja3", impersonate\="chrome110", proxies\=proxies)
proxies \= {"https": "socks://localhost:3128"}
r \= requests.get("https://tools.scrapfly.io/api/fp/ja3", impersonate\="chrome110", proxies\=proxies)
### Sessions[¶](https://curl-cffi.readthedocs.io/en/v0.9.0/#sessions "Link to this heading")
s \= requests.Session()
\# httpbin is a http test website
s.get("https://httpbin.org/cookies/set/foo/bar")
print(s.cookies)
\# \]>
r \= s.get("https://httpbin.org/cookies")
print(r.json())
\# {'cookies': {'foo': 'bar'}}
### asyncio[¶](https://curl-cffi.readthedocs.io/en/v0.9.0/#asyncio "Link to this heading")
from curl\_cffi.requests import AsyncSession
async with AsyncSession() as s:
r \= await s.get("https://example.com")
More concurrency:
import asyncio
from curl\_cffi.requests 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)
### WebSockets[¶](https://curl-cffi.readthedocs.io/en/v0.9.0/#websockets "Link to this heading")
from curl\_cffi.requests import Session, WebSocket
def on\_message(ws: WebSocket, message):
print(message)
with Session() as s:
ws \= s.ws\_connect(
"wss://api.gemini.com/v1/marketdata/BTCUSD",
on\_message\=on\_message,
)
ws.run\_forever()
Sponsor[¶](https://curl-cffi.readthedocs.io/en/v0.9.0/#sponsor "Link to this heading")
---------------------------------------------------------------------------------------
Click [here](https://buymeacoffee.com/yifei)
to buy me a coffee.
### Bypass Cloudflare with API[¶](https://curl-cffi.readthedocs.io/en/v0.9.0/#bypass-cloudflare-with-api "Link to this heading")
[](https://yescaptcha.com/i/stfnIO)
[Yescaptcha](https://yescaptcha.com/i/stfnIO)
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.
### ScrapeNinja[¶](https://curl-cffi.readthedocs.io/en/v0.9.0/#scrapeninja "Link to this heading")
[](https://scrapeninja.net/?utm_source=github&utm_medium=banner&utm_campaign=cffi)
[ScrapeNinja](https://scrapeninja.net/?utm_source=github&utm_medium=banner&utm_campaign=cffi)
is a web scraping API with two engines: fast, with high performance and TLS fingerprint; and slower with a real browser under the hood.
ScrapeNinja handles headless browsers, proxies, timeouts, retries, and helps with data extraction, so you can just get the data in JSON. Rotating proxies are available out of the box on all subscription plans.
Indices and tables[¶](https://curl-cffi.readthedocs.io/en/v0.9.0/#indices-and-tables "Link to this heading")
=============================================================================================================
* [Index](https://curl-cffi.readthedocs.io/en/v0.9.0/genindex.html)
* [Module Index](https://curl-cffi.readthedocs.io/en/v0.9.0/py-modindex.html)
* [Search Page](https://curl-cffi.readthedocs.io/en/v0.9.0/search.html)
[curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.9.0/#)
===========================================================
### Navigation
Contents:
* [Install](https://curl-cffi.readthedocs.io/en/v0.9.0/install.html)
* [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.9.0/impersonate.html)
* [Cookies](https://curl-cffi.readthedocs.io/en/v0.9.0/cookies.html)
* [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.9.0/advanced.html)
* [Exceptions](https://curl-cffi.readthedocs.io/en/v0.9.0/exceptions.html)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.9.0/vs-requests.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/v0.9.0/faq.html)
* [API References](https://curl-cffi.readthedocs.io/en/v0.9.0/api.html)
* [Change Log](https://curl-cffi.readthedocs.io/en/v0.9.0/changelog.html)
### Related Topics
* [Documentation overview](https://curl-cffi.readthedocs.io/en/v0.9.0/#)
* Next: [Install](https://curl-cffi.readthedocs.io/en/v0.9.0/install.html "next chapter")
---
# Asyncio — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/latest/genindex.html "General Index")
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/latest/index.html)
»
* [Asyncio](https://curl-cffi.readthedocs.io/en/latest/asyncio.html)
Asyncio[¶](https://curl-cffi.readthedocs.io/en/latest/asyncio.html#asyncio "Link to this heading")
===================================================================================================
TODO
### This Page
* [Show Source](https://curl-cffi.readthedocs.io/en/latest/_sources/asyncio.rst.txt)
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/latest/genindex.html "General Index")
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/latest/index.html)
»
* [Asyncio](https://curl-cffi.readthedocs.io/en/latest/asyncio.html)
---
# WebSockets — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/latest/genindex.html "General Index")
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/latest/index.html)
»
* [WebSockets](https://curl-cffi.readthedocs.io/en/latest/websockets.html)
WebSockets[¶](https://curl-cffi.readthedocs.io/en/latest/websockets.html#websockets "Link to this heading")
============================================================================================================
`curl_cffi` provides WebSocket clients for both synchronous and asynchronous contexts.
Important
**Recommendation: Use Async**
The asynchronous implementation (`AsyncWebSocket`) is significantly more developed, robust, and feature-rich than the synchronous version. It features a **decoupled I/O model** (background readers/writers), flow control, configurable backpressure, and automatic retries.
Unless you are strictly bound to a synchronous environment, we strongly recommend using the **Async** API described below for all use cases.
Quick Start[¶](https://curl-cffi.readthedocs.io/en/latest/websockets.html#quick-start "Link to this heading")
--------------------------------------------------------------------------------------------------------------
The recommended way to use WebSockets is via the `AsyncSession`.
Note
**Syntax**: The `ws_connect` method supports the standard async context manager syntax.
**Recommended:** `async with session.ws_connect(...) as ws:`
import asyncio
from curl\_cffi import AsyncSession
async def main():
async with AsyncSession() as session:
\# Connect using the standard context manager syntax
async with session.ws\_connect("wss://echo.websocket.org") as ws:
\# Send a text message
await ws.send\_str("Hello, World!")
\# Receive a text message
msg \= await ws.recv\_str()
print(f"Received: {msg}")
\# Iterate over messages
async for message in ws:
print(f"Stream: {message}")
asyncio.run(main())
Async WebSockets[¶](https://curl-cffi.readthedocs.io/en/latest/websockets.html#async-websockets "Link to this heading")
------------------------------------------------------------------------------------------------------------------------
The `AsyncWebSocket` client is powered by libcurl and tuned for high-performance asyncio applications. It supports standard features like text/binary frames, pings, and automatic handling of control frames.
**Architecture**
This implementation uses a **decoupled I/O model** to ensure high performance:
1. **Outgoing**: Messages are queued for delivery (non-blocking unless queue full).
2. **Incoming**: A background task continuously reads from the network and populates a receive queue.
This design decouples your application logic from network speeds. Even if your code processes messages slowly, the underlying network socket remains unblocked, allowing for maximum concurrency and throughput.
Connecting[¶](https://curl-cffi.readthedocs.io/en/latest/websockets.html#connecting "Link to this heading")
------------------------------------------------------------------------------------------------------------
Use `ws_connect` from an `AsyncSession`. This method accepts the same network parameters as standard HTTP requests.
**Key Features:**
* **Impersonation**: Use `impersonate="chrome"` to mimic browser fingerprints.
* **Cookies**: Automatically inherits cookies from the `AsyncSession`, and merges any new cookies passed to the method.
* **Proxies**: Supports HTTP/HTTPS/SOCKS proxies.
async with AsyncSession() as session:
\# Session cookies are automatically included
session.cookies.set("session\_id", "xyz")
async with session.ws\_connect(
"wss://api.example.com/v1/stream",
impersonate\="chrome",
auth\=("user", "pass"),
params\={"stream\_id": "123"},
timeout\=10 \# Connection timeout
) as ws:
...
Sending Data[¶](https://curl-cffi.readthedocs.io/en/latest/websockets.html#sending-data "Link to this heading")
----------------------------------------------------------------------------------------------------------------
Methods for sending data place the message into an outgoing queue. They are generally non-blocking unless the send queue size limit is reached.
\# Send text
await ws.send\_str("Hello")
\# Send bytes
await ws.send\_bytes(b"\\x00\\x01\\x02")
\# Send JSON (automatically serializes dict to JSON string)
await ws.send\_json({"action": "subscribe", "channel": "btc\_usd"})
\# Send generic (accepts str, bytes, bytearray, memoryview)
await ws.send("Auto-detected payload")
**Pings**
Libcurl handles Pongs automatically, but you can send a manual Ping frame if needed (e.g., application-layer keepalive).
await ws.ping(b"keepalive")
Receiving Data[¶](https://curl-cffi.readthedocs.io/en/latest/websockets.html#receiving-data "Link to this heading")
--------------------------------------------------------------------------------------------------------------------
You can receive individual messages or iterate over the connection.
### Receive Methods[¶](https://curl-cffi.readthedocs.io/en/latest/websockets.html#receive-methods "Link to this heading")
All receive methods support an optional `timeout` argument (in seconds).
\# Receive as string (decodes utf-8 automatically)
msg \= await ws.recv\_str()
\# Receive with a 5-second timeout
try:
data \= await ws.recv\_json(timeout\=5.0)
except WebSocketTimeout:
print("No message received in 5 seconds")
\# Receive raw bytes and frame flags
\# Useful for inspecting frame types (e.g., checking for CONTINUATION flags)
content, flags \= await ws.recv()
Concurrent calls to receive methods are fully supported. Messages are distributed to waiters in FIFO order, unlike many other libraries that limit consumption to a single task.
### Async Iteration[¶](https://curl-cffi.readthedocs.io/en/latest/websockets.html#async-iteration "Link to this heading")
The most pythonic way to consume a stream is iteration.
Note
Iteration yields `bytes`. If you expect text, you must decode it yourself.
async for message in ws:
print(message.decode("utf-8"))
Lifecycle Management[¶](https://curl-cffi.readthedocs.io/en/latest/websockets.html#lifecycle-management "Link to this heading")
--------------------------------------------------------------------------------------------------------------------------------
### Closing[¶](https://curl-cffi.readthedocs.io/en/latest/websockets.html#closing "Link to this heading")
The context manager handles closing automatically. If you need to close manually:
await ws.close()
\# Or with a custom code/reason
await ws.close(code\=1000, message\=b"bye")
\# Forcefully terminate the connection
ws.terminate()
Both methods are idempotent and safe to call multiple times. While `close()` waits for cleanup, `terminate()` is thread and task-safe, allowing for immediate disconnection from any thread without waiting for a graceful shutdown.
### Flushing[¶](https://curl-cffi.readthedocs.io/en/latest/websockets.html#flushing "Link to this heading")
Because `send()` is decoupled from the network, returning from `await send()` only means the message is queued. Use `flush()` to ensure all queued messages have effectively been written to the socket.
await ws.send\_str("Critical Data")
await ws.flush() \# Blocks until the send queue is empty
You rarely need to call flush if `send_queue_size` is small (the default). Use it only when you must verify all messages are sent before the next step in your code.
Error Handling[¶](https://curl-cffi.readthedocs.io/en/latest/websockets.html#error-handling "Link to this heading")
--------------------------------------------------------------------------------------------------------------------
Network errors are raised as `WebSocketError` or its subclasses.
from curl\_cffi import WebSocketClosed, WebSocketTimeout, WebSocketError
try:
msg \= await ws.recv\_str()
except WebSocketClosed as e:
print(f"Closed: {e.code} - {e.message}")
except WebSocketTimeout:
print("Did not receive a message in time.")
except WebSocketError as e:
print(f"Transport/Network error: {e}")
Advanced Configuration[¶](https://curl-cffi.readthedocs.io/en/latest/websockets.html#advanced-configuration "Link to this heading")
------------------------------------------------------------------------------------------------------------------------------------
The `AsyncWebSocket` implementation allows fine-tuning for high-performance scenarios.
### Queue Sizes (Backpressure)[¶](https://curl-cffi.readthedocs.io/en/latest/websockets.html#queue-sizes-backpressure "Link to this heading")
You can control the internal buffer sizes to manage backpressure.
* **recv\_queue\_size** (default: 32): Max incoming messages to buffer.
* **send\_queue\_size** (default: 16): Max outgoing messages to buffer.
* **block\_on\_recv\_queue\_full** (default: `True`): The background reader pauses when the queue is full (TCP backpressure). If `False`, the connection will fail instead (`OUT_OF_MEMORY`) to avoid stalling the reader.
\# Increase queues for high-throughput streams (e.g., market data)
ws \= await session.ws\_connect(
url,
recv\_queue\_size\=256,
send\_queue\_size\=32
)
### Message Limits[¶](https://curl-cffi.readthedocs.io/en/latest/websockets.html#message-limits "Link to this heading")
* **max\_message\_size** (default: 4MB): The maximum allowed size for a single received message. Messages larger than this will raise a `WebSocketError` (Too Large) and close the connection.
\# Allow large received payloads (e.g. 16MB)
ws \= await session.ws\_connect(url, max\_message\_size\=16 \* 1024 \* 1024)
There are no limits on the size of the message that can be sent. Messages larger than 64KB are broken into chunks of that size and sent using the [CURLWS\_CONT](https://everything.curl.dev/helpers/ws/write.html#curlws_cont)
flag which means it arrives as a single logical message on the server.
### Frame Coalescing (Throughput)[¶](https://curl-cffi.readthedocs.io/en/latest/websockets.html#frame-coalescing-throughput "Link to this heading")
For chatty protocols sending many small messages, you can enable **coalescing**. This merges multiple queued message payloads from the send queue into a single message.
* **coalesce\_frames** (default: `False`): Enable batching.
* **max\_send\_batch\_size** (default: 32): Max messages to merge.
\# Optimize for throughput over latency
ws \= await session.ws\_connect(url, coalesce\_frames\=True)
### Reliability & Retries[¶](https://curl-cffi.readthedocs.io/en/latest/websockets.html#reliability-retries "Link to this heading")
* **drain\_on\_error** (default: `False`): When a network error occurs, `recv()` will continue to yield buffered messages in the queue before raising the exception. Helps ensure data integrity on unstable connections.
* **ws\_retry**: A policy object to configure automatic retries on failed message receive operations.
from curl\_cffi import WebSocketRetryStrategy
\# Retry transient read errors up to 5 times
retry\_policy \= WebSocketRetryStrategy(
retry\=True,
count\=5
)
ws \= await session.ws\_connect(
url,
drain\_on\_error\=True,
ws\_retry\=retry\_policy
)
### Cooperative Multitasking[¶](https://curl-cffi.readthedocs.io/en/latest/websockets.html#cooperative-multitasking "Link to this heading")
To prevent the background I/O tasks from starving the asyncio event loop during heavy load, you can tune the time slicing.
* **recv\_time\_slice** (default: 0.005s): Max time spent processing incoming messages before yielding.
* **send\_time\_slice** (default: 0.001s): Max time spent sending messages before yielding.
\# Force more frequent yields for lower latency in other async tasks
ws \= await session.ws\_connect(url, recv\_time\_slice\=0.001)
### [Table of Contents](https://curl-cffi.readthedocs.io/en/latest/index.html)
* [WebSockets](https://curl-cffi.readthedocs.io/en/latest/websockets.html#)
* [Quick Start](https://curl-cffi.readthedocs.io/en/latest/websockets.html#quick-start)
* [Async WebSockets](https://curl-cffi.readthedocs.io/en/latest/websockets.html#async-websockets)
* [Connecting](https://curl-cffi.readthedocs.io/en/latest/websockets.html#connecting)
* [Sending Data](https://curl-cffi.readthedocs.io/en/latest/websockets.html#sending-data)
* [Receiving Data](https://curl-cffi.readthedocs.io/en/latest/websockets.html#receiving-data)
* [Receive Methods](https://curl-cffi.readthedocs.io/en/latest/websockets.html#receive-methods)
* [Async Iteration](https://curl-cffi.readthedocs.io/en/latest/websockets.html#async-iteration)
* [Lifecycle Management](https://curl-cffi.readthedocs.io/en/latest/websockets.html#lifecycle-management)
* [Closing](https://curl-cffi.readthedocs.io/en/latest/websockets.html#closing)
* [Flushing](https://curl-cffi.readthedocs.io/en/latest/websockets.html#flushing)
* [Error Handling](https://curl-cffi.readthedocs.io/en/latest/websockets.html#error-handling)
* [Advanced Configuration](https://curl-cffi.readthedocs.io/en/latest/websockets.html#advanced-configuration)
* [Queue Sizes (Backpressure)](https://curl-cffi.readthedocs.io/en/latest/websockets.html#queue-sizes-backpressure)
* [Message Limits](https://curl-cffi.readthedocs.io/en/latest/websockets.html#message-limits)
* [Frame Coalescing (Throughput)](https://curl-cffi.readthedocs.io/en/latest/websockets.html#frame-coalescing-throughput)
* [Reliability & Retries](https://curl-cffi.readthedocs.io/en/latest/websockets.html#reliability-retries)
* [Cooperative Multitasking](https://curl-cffi.readthedocs.io/en/latest/websockets.html#cooperative-multitasking)
### This Page
* [Show Source](https://curl-cffi.readthedocs.io/en/latest/_sources/websockets.rst.txt)
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/latest/genindex.html "General Index")
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/latest/index.html)
»
* [WebSockets](https://curl-cffi.readthedocs.io/en/latest/websockets.html)
---
# Search — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/latest/genindex.html "General Index")
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/latest/index.html)
»
* [Search](https://curl-cffi.readthedocs.io/en/latest/search.html)
Search
======
Searching for multiple words only shows matches that contain all words.
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/latest/genindex.html "General Index")
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/latest/index.html)
»
* [Search](https://curl-cffi.readthedocs.io/en/latest/search.html)
---
# Unknown
.. curl\_cffi documentation master file, created by sphinx-quickstart on Sat Feb 17 22:22:59 2024. You can adapt this file completely to your liking, but it should at least contain the root \`toctree\` directive. curl\_cffi's documentation ========================= .. toctree:: :maxdepth: 2 :caption: Contents: :glob: quick\_start impersonate/\_index advanced vs-requests cookies community api faq changelog dev \`Discuss on Telegram\`\_ .. \_Discuss on Telegram: https://t.me/+lL9n33eZp480MGM1 curl\_cffi is a Python binding for \`curl-impersonate fork\`\_ via \`cffi\`\_. For commercial support, visit \`impersonate.pro \`\_. .. \_curl-impersonate fork: https://github.com/lexiforest/curl-impersonate .. \_cffi: https://cffi.readthedocs.io/en/latest/ Unlike other pure Python http clients like \`\`httpx\`\` or \`\`requests\`\`, \`\`curl\_cffi\`\` can impersonate browsers' TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try. If you are looking for Python http3 clients, curl\_cffi added http3 support since \`\`v0.11\`\`. Sponsors -------- Bypass Cloudflare with API ~~~~~~~~~~~~~~~~~~~~~~~~~~ .. image:: https://raw.githubusercontent.com/lexiforest/curl\_cffi/main/assets/yescaptcha.png :width: 149 :alt: YesCaptcha :target: https://yescaptcha.com/i/stfnIO \`Yescaptcha \`\_ is a proxy service that bypasses Cloudflare and uses the API interface to obtain verified cookies (e.g. \`\`cf\_clearance\`\`). Click \`here \`\_ to register. You can also click \`here \`\_ to buy me a coffee. Residential Proxies ~~~~~~~~~~~~~~~~~~~ .. image:: https://raw.githubusercontent.com/lexiforest/curl\_cffi/main/assets/thordata.png :width: 149 :alt: Thordata :target: https://www.thordata.com/?ls=github&lk=curl\_cffi \`Thordata \`\_: A reliable and cost-effective proxy service provider. One-click collection of public network data, providing enterprises and developers with stable, efficient, and compliant global proxy IP services. Register for a free trial of \`residential proxies \`\_ and receive 2000 free SERP API calls. 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 \`\_. - Mimics 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 & 3.0, which requests does not. - Supports websocket. .. list-table:: Feature matrix :widths: 20 16 16 16 16 16 :header-rows: 1 \* - - requests - aiohttp - httpx - pycurl - curl\_cffi \* - http2 - ❌ - ❌ - ✅ - ✅ - ✅ \* - http3 - ❌ - ❌ - ❌ - ✅ - ✅ \* - sync - ✅ - ❌ - ✅ - ✅ - ✅ \* - async - ❌ - ✅ - ✅ - ❌ - ✅ \* - websocket - ❌ - ✅ - ❌ - ❌ - ✅ \* - native retry - ❌ - ❌ - ❌ - ❌ - ✅ \* - fingerprints - ❌ - ❌ - ❌ - ❌ - ✅ \* - speed - 🐇 - 🐇🐇 - 🐇 - 🐇🐇 - 🐇🐇 Notes: 1. For pycurl, you need a http/3 enabled libcurl, while curl\_cffi packages libcurl-impersonate inside Python wheels. 2. Full http/3 supported was added in v0.12.0. Install ------- .. code-block:: sh pip install curl\_cffi --upgrade For more details, see :doc:\`quick\_start\`. Documentation ------------- You can first check out :doc:\`quick\_start\`. Then the :doc:\`impersonate\`. For advanced topics, checkout :doc:\`cookies\`, :doc:\`asyncio\` and :doc:\`websockets\`. You can also find common use cases in the \`examples \`\_ directory. Finally, if something is missing from the tutorial, you can always find them in the :doc:\`api\`. If you have any questions, be sure to check out the :doc:\`faq\` section before opening an issue. Indices and tables ================== \* :ref:\`genindex\` \* :ref:\`modindex\` \* :ref:\`search\`
---
# Index — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html# "General Index")
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Index](https://curl-cffi.readthedocs.io/en/stable/genindex.html)
Index
=====
[**\_**](https://curl-cffi.readthedocs.io/en/stable/genindex.html#_)
| [**A**](https://curl-cffi.readthedocs.io/en/stable/genindex.html#A)
| [**C**](https://curl-cffi.readthedocs.io/en/stable/genindex.html#C)
| [**D**](https://curl-cffi.readthedocs.io/en/stable/genindex.html#D)
| [**E**](https://curl-cffi.readthedocs.io/en/stable/genindex.html#E)
| [**F**](https://curl-cffi.readthedocs.io/en/stable/genindex.html#F)
| [**G**](https://curl-cffi.readthedocs.io/en/stable/genindex.html#G)
| [**H**](https://curl-cffi.readthedocs.io/en/stable/genindex.html#H)
| [**I**](https://curl-cffi.readthedocs.io/en/stable/genindex.html#I)
| [**J**](https://curl-cffi.readthedocs.io/en/stable/genindex.html#J)
| [**L**](https://curl-cffi.readthedocs.io/en/stable/genindex.html#L)
| [**M**](https://curl-cffi.readthedocs.io/en/stable/genindex.html#M)
| [**O**](https://curl-cffi.readthedocs.io/en/stable/genindex.html#O)
| [**P**](https://curl-cffi.readthedocs.io/en/stable/genindex.html#P)
| [**R**](https://curl-cffi.readthedocs.io/en/stable/genindex.html#R)
| [**S**](https://curl-cffi.readthedocs.io/en/stable/genindex.html#S)
| [**T**](https://curl-cffi.readthedocs.io/en/stable/genindex.html#T)
| [**U**](https://curl-cffi.readthedocs.io/en/stable/genindex.html#U)
| [**V**](https://curl-cffi.readthedocs.io/en/stable/genindex.html#V)
| [**W**](https://curl-cffi.readthedocs.io/en/stable/genindex.html#W)
\_
--
| | |
| --- | --- |
| * [\_\_delitem\_\_() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies.__delitem__) * [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.__delitem__)
* [ChunkedEncodingError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.ChunkedEncodingError)
* [ContentDecodingError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.ContentDecodingError)
* [CookieConflict (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.CookieConflict)
* [Cookies (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies)
* [ImpersonateError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.ImpersonateError)
* [IncompleteRead (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.IncompleteRead)
* [InterfaceError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.InterfaceError)
* [InvalidHeader (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.InvalidHeader) | * [InvalidJSONError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.InvalidJSONError)
* [InvalidProxyURL (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.InvalidProxyURL)
* [InvalidSchema (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.InvalidSchema)
* [InvalidURL (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.InvalidURL)
* [ReadTimeout (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.ReadTimeout)
* [RequestException (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.RequestException)
* [RequestsDependencyWarning (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.RequestsDependencyWarning)
* [RequestsWarning (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.RequestsWarning)
* [ws\_send() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.ws_send) |
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html# "General Index")
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Index](https://curl-cffi.readthedocs.io/en/stable/genindex.html)
---
# Quick Start — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/impersonate/_index.html "Impersonate Guide")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/index.html "curl_cffi’s documentation")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Quick Start](https://curl-cffi.readthedocs.io/en/stable/quick_start.html)
Quick Start[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#quick-start "Link to this heading")
===============================================================================================================
Install[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#install "Link to this heading")
-------------------------------------------------------------------------------------------------------
Note: We only support Python 3.9 and above. Python 3.8 has reached its end of life.
### Via pip[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#via-pip "Link to this heading")
The simplest way is to install from PyPI:
pip install curl\_cffi \--upgrade
We have sdist(source distribution) and bdist(binary distribution) on PyPI. This should work on Linux, macOS and Windows out of the box.
If it does not work on you platform, you may need to compile and install `curl-impersonate` first and set some environment variables like `LD_LIBRARY_PATH`.
### Beta versions[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#beta-versions "Link to this heading")
To install beta releases:
pip install curl\_cffi \--upgrade \--pre
Note the `--pre` option here means pre-releases.
### Latest[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#latest "Link to this heading")
To install the latest unstable version from GitHub:
git clone https://github.com/lexiforest/curl\_cffi/
cd curl\_cffi
make preprocess
pip install .
Or you can download the wheels from github actions artifacts.
requests-like[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#requests-like "Link to this heading")
-------------------------------------------------------------------------------------------------------------------
`curl_cffi` tries to follow the `requests` API when possible, if you are already of guru using requests, read the warning part in this page, skip other parts and head over to the [Compatibility with requests](https://curl-cffi.readthedocs.io/en/stable/vs-requests.html)
.
### Basic GET requests[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#basic-get-requests "Link to this heading")
Basic `GET` request and using the `impersonate` parameter.
import curl\_cffi
url \= "https://tls.browserleaks.com/json"
\# Notice the impersonate parameter
r \= curl\_cffi.get("https://tls.browserleaks.com/json", impersonate\="chrome110")
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")
\# http/socks proxies are supported
proxies \= {"https": "http://localhost:3128"}
r \= curl\_cffi.get("https://tls.browserleaks.com/json", impersonate\="chrome110", proxies\=proxies)
proxies \= {"https": "socks://localhost:3128"}
r \= curl\_cffi.get("https://tls.browserleaks.com/json", impersonate\="chrome110", proxies\=proxies)
### URL params[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#url-params "Link to this heading")
Messing with the URLs:
import curl\_cffi
\>>> params \= {"foo": "bar"}
\>>> r \= requests.get("http://httpbin.org/get", params\=params)
\>>> r.url
'http://httpbin.org/get?foo=bar'
\>>> params \= {'key1': 'value1', 'key2': \['value2', 'value3'\]}
\>>> import curl\_cffi
\>>> r \= curl\_cffi.get('https://httpbin.org/get', params\=params)
\>>> r.url
'https://httpbin.org/get?key1=value1&key2=value2&key2=value3'
### Headers[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#headers "Link to this heading")
Additional headers can be override with `headers=...`.
headers \= {"User-Agent": "curl\_cffi/0.11.2"}
r \= curl\_cffi.get("http://example.com", headers\=headers)
Warning
In curl\_cffi, if you set `impersonate=...`, by default, the corresponding headers will be added, you can:
1. Add your headers to override them.
2. Use `default_headers=False` to completely turn off the default headers.
\>>> r \= curl\_cffi.get("https://httpbin.org/headers", impersonate\="chrome")
\>>> print(r.text)
{
"headers": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,\*/\*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"Accept-Encoding": "gzip, deflate, br, zstd",
"Accept-Language": "en-US,en;q=0.9",
"Host": "httpbin.org",
"Priority": "u=0, i",
"Sec-Ch-Ua": "\\"Chromium\\";v=\\"136\\", \\"Google Chrome\\";v=\\"136\\", \\"Not.A/Brand\\";v=\\"99\\"",
"Sec-Ch-Ua-Mobile": "?0",
"Sec-Ch-Ua-Platform": "\\"macOS\\"",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "none",
"Sec-Fetch-User": "?1",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10\_15\_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36",
"X-Amzn-Trace-Id": "Root=1-68452cc9-7287427f222e720c57971297"
}
}
\>>> r \= curl\_cffi.get("https://httpbin.org/headers", impersonate\="chrome", default\_headers\=False)
\>>> print(r.text)
{
"headers": {
"Accept": "\*/\*",
"Accept-Encoding": "gzip, deflate, br",
"Host": "httpbin.org",
"X-Amzn-Trace-Id": "Root=1-68452d20-2cf4cf00201987301c476c06"
}
}
### Reading Response[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#reading-response "Link to this heading")
Like requests, you can read the response content in the following ways:
Reading the binary content as bytes:
\>>> r \= curl\_cffi.get("https://example.com")
\>>> r.content
b'\\n\\n
\\n...'
Reading the decoded content as str:
\>>> r \= curl\_cffi.get("https://example.com")
\>>> r.text
'\\n\\n\\n...'
By default, `curl_cffi` first use the `encoding` attribute if given, then tries to use the `Content-Type` header to decode the content, If not found, will fallback to `default_encoding`, then to “utf-8”.
\# force override with .encoding
\>>> r.encoding \= 'latin-1'
### POST and uploads[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#post-and-uploads "Link to this heading")
Of course, we also support `POST`, `PUT`, `DELETE` etc.
#### Form submit[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#form-submit "Link to this heading")
Use the `data={...}` option.
Note
The “application/x-www-form-urlencoded” will be automatically added.
\>>> r \= curl\_cffi.post("https://httpbin.org/post", data\={"name": "Luke"})
\>>> print(r.text)
{
"args": {},
"form": {
"name": "Luke"
},
...
}
#### Binary data[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#binary-data "Link to this heading")
Still, use the `data=b"..."` option.
\>>> r \= curl\_cffi.post("https://httpbin.org/post", data\=b"LukeSkywalker")
\>>> print(r.text)
{
"args": {},
"data": "LukeSkywalker",
"files": {},
"form": {},
...
}
#### Posting JSON[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#posting-json "Link to this heading")
Use the `json=...` option.
Note
The “application/json” will be automatically added.
\>>> r \= curl\_cffi.post("https://httpbin.org/post", json\={"name": "Luke"})
\>>> print(r.text)
{
"args": {},
"data": "{\\"name\\":\\"Luke\\"}",
"files": {},
"form": {},
...
}
#### Uploads[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#uploads "Link to this heading")
Warning
curl\_cffi does not support the `files=...` API. Use `multipart=...` instead.
For uploading files, the `requests` API is horrible, we provide a similar but cleaner way:
mp \= curl\_cffi.CurlMime()
mp.addpart(
name\="attachment", \# field name in the form
content\_type\="image/png", \# mime type
filename\="image.png", \# filename seen by remote server
local\_path\="./image.png", \# local file to upload
data\=file.read(), \# if you already have the data in memory
)
r \= curl\_cffi.post("https://httpbin.org/post", data\={"foo": "bar"}, multipart\=mp)
print(r.json())
All the fields in the API are explicit. For advanced usage: see [examples](https://github.com/lexiforest/curl_cffi/blob/main/examples/upload.py)
.
### Compressed response[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#compressed-response "Link to this heading")
Currently, we forcefully decode compressed response, but this may be changed in the future.
curl\_cffi supports gzip/brotli/zstd natively.
If the response content is `json`, you can parse them directly:
\>>> r \= curl\_cffi.get("https://httpbin.org/headers")
\>>> r.json()
{'headers': {'Accept': '\*/\*', 'Accept-Encoding': 'gz...')
### Response status[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#response-status "Link to this heading")
\>>> r \= curl\_cffi.get('https://httpbin.org/get')
\>>> r.status\_code
200
\>>> r \= curl\_cffi.get("https://httpbin.org/status/404")
\>>> r.status\_code
404
\>>> r.raise\_for\_status()
Traceback (most recent call last):
File "", line 1, in
File "/Users/.../repos/curl\_cffi/curl\_cffi/requests/models.py", line 167, in raise\_for\_status
raise HTTPError(f"HTTP Error {self.status\_code}: {self.reason}", 0, self)
curl\_cffi.requests.exceptions.HTTPError: HTTP Error 404:
### Response headers[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#response-headers "Link to this heading")
Response headers is a case-insensitive dict.
\>>> r.headers
Headers({'date': 'Sun, 08 Jun 2025 06:58:15 GMT', 'content-type': 'application/json', 'content-length': '184', 'server': 'gunicorn/19.9.0', 'access-control-allow-origin': '\*', 'access-control-allow-credentials': 'true'})
\>>> r.headers\["content-type"\]
'application/json'
For a complete list of response attributes, see the [API References](https://curl-cffi.readthedocs.io/en/stable/api.html)
.
### Streaming response[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#streaming-response "Link to this heading")
For compatibility, curl\_cffi supports the `stream=True` option, and a `stream` method, with iterative-style content streaming.
But when possible, you should choose the native `content_callback` option.
r \= curl\_cffi.get(
\>>> r \= curl\_cffi.get("https://httpbin.org/stream/20", stream\=True)
\>>> for chunk in r.iter\_content():
... print("CHUNK", chunk)
...
CHUNK b'{"url": "https://httpbin.org/stream/20",...'
CHUNK b'{"url": "https://httpbin.org/stream/20",...'
For more examples, see the [examples on GitHub](https://github.com/lexiforest/curl_cffi/blob/main/examples/stream.py)
Warning
Natively, libcurl only support a callback-style API, i.e. you pass a callback function for processing the streamed response content. In curl\_cffi, we use a internal queue to convert the callback to a interative API.
Because of the limitation, when a request is sent, the response will start to be streamed to your client at once. You need to start consuming the content immediately, otherwise, it would be store in your memory, thus OOM could be triggered.
Alternatively, you should use the native `content_callback` API.
\>>> def callback(chunk):
... print("CHUNK", chunk)
...
\>>> r \= curl\_cffi.get("https://httpbin.org/stream/20", content\_callback\=callback)
CHUNK b'{"url": "https://httpbin.org/stream/20"...'
CHUNK b'{"url": "https://httpbin.org/stream/20"...'
### Redirection and history[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#redirection-and-history "Link to this heading")
`curl_cffi` automatically follows redirects, use `allow_redirects=False` to disable it.
\>>> r \= curl\_cffi.get("https://httpbin.org/redirect-to?url=/")
\>>> r.url
'https://httpbin.org/'
\>>> r \= requests.get("https://httpbin.org/redirect-to?url=/", allow\_redirects\=False)
\>>> r.url
'https://httpbin.org/redirect-to?url=/'
\>>> r.status\_code
302
Warning
History is not implemented.
### Authenticate[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#authenticate "Link to this heading")
You can use the `auth` parameter or URL to add http `basic auth` credentials.
\>>> curl\_cffi.get("https://example.com", auth\=("my\_user", "password123"))
\>>> curl\_cffi.get("https://user:password@example.com")
Digest auth is dangerous and [deprecated](https://en.wikipedia.org/wiki/Digest_access_authentication#Disadvantages)
, we do not support that. Although, you should be able to use it with low-level curl options.
### Sessions and cookies[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#sessions-and-cookies "Link to this heading")
We also provide Session to persist cookies and reuse connections.
Note
You should always use a session whenever possible.
s \= curl\_cffi.Session()
\# Cookies from server are stored in session
s.get("https://httpbin.org/cookies/set/foo/bar")
print(s.cookies)
\# \]>
\# Cookies are used in next request
r \= s.get("https://httpbin.org/cookies")
print(r.json())
\# {'cookies': {'foo': 'bar'}}
\# It's preferred to use a context manager
with curl\_cffi.Session() as s:
r \= s.get("https://example.com")
If you want to set a global option in `Session`, you can use the same parameter in `request`.
with curl\_cffi.Session(headers\={"User-Agent": "curl\_cffi/0.11"}) as s:
r \= s.get("https://example.com")
For a complete list, see [API References](https://curl-cffi.readthedocs.io/en/stable/api.html)
#### Response vs Session cookies[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#response-vs-session-cookies "Link to this heading")
The `response.cookies` object contains only cookies from current request. Be aware, if you hit a redirect, response cookies may be incomplete, it’s almost always better to use a session.
import curl\_cffi
r \= curl\_cffi.get("https://httpbin.org/redirect")
\# ❌ Cookie from previous redirect may be lost.
do\_something(r.cookies)
s \= curl\_cffi.Session()
r \= s.get("https://httpbin.org/redirect")
\# ✅ Use a session instead, to retrive all cookies in the session
do\_something(s.cookies)
#### Use session without cookies[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#use-session-without-cookies "Link to this heading")
If you want to use a session, but somehow you need to discard all the cookies. You can use the `discard_cookies` option to discard cookies in session.
s \= curl\_cffi.Session(discard\_cookies\=True)
Asyncio[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#asyncio "Link to this heading")
-------------------------------------------------------------------------------------------------------
Besides the regular sync API, `curl_cffi` also provides a very similar `asyncio` API.
\# You must use a session for asyncio
async with curl\_cffi.AsyncSession() as s:
r \= await s.get("https://example.com")
The benefit of asyncio is easier way to implement more concurrency:
import asyncio
from curl\_cffi import AsyncSession
urls \= \[\
"https://google.com/",\
"https://facebook.com/",\
"https://apple.com/",\
\]
async with AsyncSession() as s:
tasks \= \[\]
for url in urls:
task \= s.get(url)
tasks.append(task)
results \= await asyncio.gather(\*tasks)
For detailed asyncio guide, see [Asyncio](https://curl-cffi.readthedocs.io/en/stable/asyncio.html)
.
WebSockets[¶](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#websockets "Link to this heading")
-------------------------------------------------------------------------------------------------------------
`curl_cffi` supports both sync and async API for websockets.
from curl\_cffi import Session, WebSocket
def on\_message(ws: WebSocket, message):
print(message)
with Session() as s:
ws \= s.ws\_connect(
"wss://api.gemini.com/v1/marketdata/BTCUSD",
on\_message\=on\_message,
)
ws.run\_forever()
\# asyncio
import asyncio
from curl\_cffi import AsyncSession
async with AsyncSession() as s:
ws \= await s.ws\_connect("wss://echo.websocket.org")
await asyncio.gather(\*\[ws.send\_str("Hello, World!") for \_ in range(10)\])
async for message in ws:
print(message)
For detailed websocket guide, see [WebSockets](https://curl-cffi.readthedocs.io/en/stable/websockets.html)
.
### [Table of Contents](https://curl-cffi.readthedocs.io/en/stable/index.html)
* [Quick Start](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#)
* [Install](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#install)
* [Via pip](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#via-pip)
* [Beta versions](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#beta-versions)
* [Latest](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#latest)
* [requests-like](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#requests-like)
* [Basic GET requests](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#basic-get-requests)
* [URL params](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#url-params)
* [Headers](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#headers)
* [Reading Response](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#reading-response)
* [POST and uploads](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#post-and-uploads)
* [Form submit](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#form-submit)
* [Binary data](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#binary-data)
* [Posting JSON](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#posting-json)
* [Uploads](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#uploads)
* [Compressed response](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#compressed-response)
* [Response status](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#response-status)
* [Response headers](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#response-headers)
* [Streaming response](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#streaming-response)
* [Redirection and history](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#redirection-and-history)
* [Authenticate](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#authenticate)
* [Sessions and cookies](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#sessions-and-cookies)
* [Response vs Session cookies](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#response-vs-session-cookies)
* [Use session without cookies](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#use-session-without-cookies)
* [Asyncio](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#asyncio)
* [WebSockets](https://curl-cffi.readthedocs.io/en/stable/quick_start.html#websockets)
#### Previous topic
[curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/stable/index.html "previous chapter")
#### Next topic
[Impersonate Guide](https://curl-cffi.readthedocs.io/en/stable/impersonate/_index.html "next chapter")
### This Page
* [Show Source](https://curl-cffi.readthedocs.io/en/stable/_sources/quick_start.rst.txt)
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/impersonate/_index.html "Impersonate Guide")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/index.html "curl_cffi’s documentation")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Quick Start](https://curl-cffi.readthedocs.io/en/stable/quick_start.html)
---
# Impersonate Guide — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/impersonate/fingerprint.html "What is TLS and http/2, http/3 fingerprinting?")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/quick_start.html "Quick Start")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Impersonate Guide](https://curl-cffi.readthedocs.io/en/stable/impersonate/_index.html)
Impersonate Guide[¶](https://curl-cffi.readthedocs.io/en/stable/impersonate/_index.html#impersonate-guide "Link to this heading")
==================================================================================================================================
You probably come across `curl_cffi` for it’s ability to impersonate browsers. Here is a tutorial on how to better impersonate using `curl_cffi`.
Contents:
* [What is TLS and http/2, http/3 fingerprinting?](https://curl-cffi.readthedocs.io/en/stable/impersonate/fingerprint.html)
* [TLS and http/2](https://curl-cffi.readthedocs.io/en/stable/impersonate/fingerprint.html#tls-and-http-2)
* [http/3](https://curl-cffi.readthedocs.io/en/stable/impersonate/fingerprint.html#http-3)
* [Supported browser impersonate targets](https://curl-cffi.readthedocs.io/en/stable/impersonate/targets.html)
* [Which target version to use?](https://curl-cffi.readthedocs.io/en/stable/impersonate/targets.html#which-target-version-to-use)
* [How to use my own fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/stable/impersonate/customize.html)
* [JA3 and Akamai String Format](https://curl-cffi.readthedocs.io/en/stable/impersonate/customize.html#ja3-and-akamai-string-format)
* [Using CURLOPTs](https://curl-cffi.readthedocs.io/en/stable/impersonate/customize.html#using-curlopts)
* [How to toggle firefox-specific extensions?](https://curl-cffi.readthedocs.io/en/stable/impersonate/customize.html#how-to-toggle-firefox-specific-extensions)
* [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/stable/impersonate/psk.html)
* [How do I enable PSK extension anyway?](https://curl-cffi.readthedocs.io/en/stable/impersonate/psk.html#how-do-i-enable-psk-extension-anyway)
* [Impersonation FAQ](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html)
* [How to check if my impersonation is working?](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html#how-to-check-if-my-impersonation-is-working)
* [I’m still being detected even if I impersonated correctly](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html#i-m-still-being-detected-even-if-i-impersonated-correctly)
* [Should I randomize my fingerprints for each request?](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html#should-i-randomize-my-fingerprints-for-each-request)
* [Can I change JavaScript fingerprints with this library?](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html#can-i-change-javascript-fingerprints-with-this-library)
* [Why are all the User-Agents macOS?](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html#why-are-all-the-user-agents-macos)
#### Previous topic
[Quick Start](https://curl-cffi.readthedocs.io/en/stable/quick_start.html "previous chapter")
#### Next topic
[What is TLS and http/2, http/3 fingerprinting?](https://curl-cffi.readthedocs.io/en/stable/impersonate/fingerprint.html "next chapter")
### This Page
* [Show Source](https://curl-cffi.readthedocs.io/en/stable/_sources/impersonate/_index.rst.txt)
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/impersonate/fingerprint.html "What is TLS and http/2, http/3 fingerprinting?")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/quick_start.html "Quick Start")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Impersonate Guide](https://curl-cffi.readthedocs.io/en/stable/impersonate/_index.html)
---
# Supported browser impersonate targets — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/impersonate/customize.html "How to use my own fingerprints? e.g. okhttp")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/impersonate/fingerprint.html "What is TLS and http/2, http/3 fingerprinting?")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Impersonate Guide](https://curl-cffi.readthedocs.io/en/stable/impersonate/_index.html)
»
* [Supported browser impersonate targets](https://curl-cffi.readthedocs.io/en/stable/impersonate/targets.html)
Supported browser impersonate targets[¶](https://curl-cffi.readthedocs.io/en/stable/impersonate/targets.html#supported-browser-impersonate-targets "Link to this heading")
===========================================================================================================================================================================
`curl_cffi` supports the same browser versions as supported by our [fork of curl-impersonate](https://github.com/lexiforest/curl-impersonate)
.
Browser versions will be added **only** when their fingerprints change. If you see a version, e.g. `chrome122`, was skipped, you can simply impersonate it with your own headers and the previous version.
If you are too busy to look up those details, you can try our commercial version at [impersonate.pro](https://impersonate.pro/)
, which has a weekly updated list of browser profiles and even more browser types.
If you are trying to impersonate a target other than a browser, use `ja3=...`, `akamai=...` and `extra_fp=...` to specify your own customized fingerprints. See below for details.
* chrome99
* chrome100
* chrome101
* chrome104
* chrome107
* chrome110
* chrome116 1
* chrome119 1
* chrome120 1
* chrome123 3
* chrome124 3
* chrome131 4
* chrome133a 5 6
* chrome136 7
* chrome99\_android
* chrome131\_android 4
* edge99
* edge101
* safari153 2
* safari155 2
* safari170 1
* safari172\_ios 1
* safari180 4
* safari180\_ios 4
* safari184 7
* safari184\_ios 7
* safari260 8
* safari260\_ios 8
* firefox133 5
* tor145 7
Notes:
1. Added in version `0.6.0`.
2. Fixed in version `0.6.0`, previous http2 fingerprints were [not correct](https://github.com/lwthiker/curl-impersonate/issues/215)
.
3. Added in version `0.7.0`.
4. Added in version `0.8.0`.
5. Added in version `0.9.0`.
6. The version postfix `-a``(e.g. ``chrome133a`) means that this is an alternative version, i.e. the fingerprint has not been officially updated by browser, but has been observed because of A/B testing.
7. Added in version `0.11.0`
8. Added in version `0.12.0`
Which target version to use?[¶](https://curl-cffi.readthedocs.io/en/stable/impersonate/targets.html#which-target-version-to-use "Link to this heading")
========================================================================================================================================================
Generally speaking, you should use the latest Chrome or Safari versions. As of v0.11, they’re `chrome136`, `safari184` and `safari184_ios`. To always impersonate the latest available browser versions, you can simply use `chrome`, `firefox`, `safari` and `chrome_android`, `safari_ios`.
import curl\_cffi
curl\_cffi.get(url, impersonate\="chrome")
Tips:
iOS has restrictions on WebView and TLS libs, so `safari_*_ios` should work for a lot of apps. If you encountered an android app with custom fingerprints, you can try the `safari_ios` fingerprints, given that this app should have an iOS version.
### [Table of Contents](https://curl-cffi.readthedocs.io/en/stable/index.html)
* [Supported browser impersonate targets](https://curl-cffi.readthedocs.io/en/stable/impersonate/targets.html#)
* [Which target version to use?](https://curl-cffi.readthedocs.io/en/stable/impersonate/targets.html#which-target-version-to-use)
#### Previous topic
[What is TLS and http/2, http/3 fingerprinting?](https://curl-cffi.readthedocs.io/en/stable/impersonate/fingerprint.html "previous chapter")
#### Next topic
[How to use my own fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/stable/impersonate/customize.html "next chapter")
### This Page
* [Show Source](https://curl-cffi.readthedocs.io/en/stable/_sources/impersonate/targets.rst.txt)
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/impersonate/customize.html "How to use my own fingerprints? e.g. okhttp")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/impersonate/fingerprint.html "What is TLS and http/2, http/3 fingerprinting?")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Impersonate Guide](https://curl-cffi.readthedocs.io/en/stable/impersonate/_index.html)
»
* [Supported browser impersonate targets](https://curl-cffi.readthedocs.io/en/stable/impersonate/targets.html)
---
# What is TLS and http/2, http/3 fingerprinting? — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/impersonate/targets.html "Supported browser impersonate targets")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/impersonate/_index.html "Impersonate Guide")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Impersonate Guide](https://curl-cffi.readthedocs.io/en/stable/impersonate/_index.html)
»
* [What is TLS and http/2, http/3 fingerprinting?](https://curl-cffi.readthedocs.io/en/stable/impersonate/fingerprint.html)
What is TLS and http/2, http/3 fingerprinting?[¶](https://curl-cffi.readthedocs.io/en/stable/impersonate/fingerprint.html#what-is-tls-and-http-2-http-3-fingerprinting "Link to this heading")
===============================================================================================================================================================================================
TLS and http/2[¶](https://curl-cffi.readthedocs.io/en/stable/impersonate/fingerprint.html#tls-and-http-2 "Link to this heading")
---------------------------------------------------------------------------------------------------------------------------------
TLS is the `s` in `https`. `https` has been uniformly deployed across the world. There are many extension and cipher suites a implementation can choose to use. According to the RFC, there are many valid combinations. But in reality, browser vendors tend to use fixed combinations, and these combinations can be used identify if the request is from a certain browser or an automated script. The digest of this combination is called a TLS fingerprints. The most common digesting method is called JA3.
Similar to TLS, there are a few settings in http/2 connection can be used to identify the source of a request. The most commonly used digesting method is proposed by Akamai, and called the Akamai http2 fingerprint.
To learn the details of TLS and http2 fingerprinting, you can read these great articles from lwthiker:
1. [https://lwthiker.com/networks/2022/06/17/tls-fingerprinting.html](https://lwthiker.com/networks/2022/06/17/tls-fingerprinting.html)
2. [https://lwthiker.com/networks/2022/06/17/http2-fingerprinting.html](https://lwthiker.com/networks/2022/06/17/http2-fingerprinting.html)
The format of JA3 and Akamai digest is briefly discussed below.
http/3[¶](https://curl-cffi.readthedocs.io/en/stable/impersonate/fingerprint.html#http-3 "Link to this heading")
-----------------------------------------------------------------------------------------------------------------
As of http/3, the newest version of http. Basically, it’s http/2 reimplemented over QUIC, thus it can be fingerprinted in a similar way with http/2.
Http3 fingerprints has not yet been publicly exploited and reported. But given the rapidly increasing marketshare of http/3(35% of internet traffic), it is expected that some strict WAF vendors have begun to utilize http/3 fingerprinting.
It has also been noticed by many users, that, for a lot of sites, there is less or even none detection when using http/3.
`curl_cffi` provides TLS and http/2 impersonation in the open source version.
For http/3 impersonation and http/3 proxy support, please head over to [impersonate.pro](https://impersonate.pro/)
for the commercial version of `curl_cffi`.
### [Table of Contents](https://curl-cffi.readthedocs.io/en/stable/index.html)
* [What is TLS and http/2, http/3 fingerprinting?](https://curl-cffi.readthedocs.io/en/stable/impersonate/fingerprint.html#)
* [TLS and http/2](https://curl-cffi.readthedocs.io/en/stable/impersonate/fingerprint.html#tls-and-http-2)
* [http/3](https://curl-cffi.readthedocs.io/en/stable/impersonate/fingerprint.html#http-3)
#### Previous topic
[Impersonate Guide](https://curl-cffi.readthedocs.io/en/stable/impersonate/_index.html "previous chapter")
#### Next topic
[Supported browser impersonate targets](https://curl-cffi.readthedocs.io/en/stable/impersonate/targets.html "next chapter")
### This Page
* [Show Source](https://curl-cffi.readthedocs.io/en/stable/_sources/impersonate/fingerprint.rst.txt)
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/impersonate/targets.html "Supported browser impersonate targets")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/impersonate/_index.html "Impersonate Guide")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Impersonate Guide](https://curl-cffi.readthedocs.io/en/stable/impersonate/_index.html)
»
* [What is TLS and http/2, http/3 fingerprinting?](https://curl-cffi.readthedocs.io/en/stable/impersonate/fingerprint.html)
---
# Advanced Topics — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/vs-requests.html "Compatibility with requests")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html "Impersonation FAQ")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Advanced Topics](https://curl-cffi.readthedocs.io/en/stable/advanced.html)
Advanced Topics[¶](https://curl-cffi.readthedocs.io/en/stable/advanced.html#advanced-topics "Link to this heading")
====================================================================================================================
Proxies[¶](https://curl-cffi.readthedocs.io/en/stable/advanced.html#proxies "Link to this heading")
----------------------------------------------------------------------------------------------------
You can use the `proxy` parameter:
import curl\_cffi
curl\_cffi.get(url, proxy\="http://user:pass@example.com:3128")
You can also use the `http_proxy`, `https_proxy`, and `ws_proxy`, `wss_proxy` environment variables, respectively.
Warning
For beginners, a very common mistake is to add `https://` prefix to the `https` proxy.
For explanation of differences between `http_proxy` and `https_proxy`, please see [#6](https://github.com/lexiforest/curl_cffi/issues/6)
.
For compatibility with `requests`, we also support using dicts.
import curl\_cffi
proxies \= {
"http": "http://localhost:3128",
"https": "http://localhost:3128"
}
curl\_cffi.get(url, proxies\=proxies)
Note
Prefer the single proxy parameter, unless you do have different proxies for http and https
Low-level curl API[¶](https://curl-cffi.readthedocs.io/en/stable/advanced.html#low-level-curl-api "Link to this heading")
--------------------------------------------------------------------------------------------------------------------------
Although we provide an easy to use `requests`\-like API, sometimes, you may prefer to use the `curl`\-like API.
The curl API is very much like what you may have used – `pycurl`, with extra impersonation support.
from curl\_cffi import Curl, CurlOpt
from io import BytesIO
buffer \= BytesIO()
c \= Curl()
c.setopt(CurlOpt.URL, b'https://tls.browserleaks.com/json')
c.setopt(CurlOpt.WRITEDATA, buffer)
c.impersonate("chrome124")
c.perform()
c.close()
body \= buffer.getvalue()
print(body.decode())
For a complete list of options, see [API References](https://curl-cffi.readthedocs.io/en/stable/api.html)
Using `CURLOPT_*` in requests API[¶](https://curl-cffi.readthedocs.io/en/stable/advanced.html#using-curlopt-in-requests-api "Link to this heading")
----------------------------------------------------------------------------------------------------------------------------------------------------
Sometimes, you know an option from libcurl, but we haven’t exposed it in the requests API. You can simply add the `curl_options` dict to apply the option.
Note
Using curl\_options is preferred over using `session.curl.setopt`, the latter may get overriden internally, while the former is executed after all options have been set.
Selecting http version[¶](https://curl-cffi.readthedocs.io/en/stable/advanced.html#selecting-http-version "Link to this heading")
----------------------------------------------------------------------------------------------------------------------------------
The recommended and default http version is http/2, the present and most widely used http version as of 2025.
According to [Wikipedia](https://en.wikipedia.org/wiki/HTTP)
, the marketshare is:
* HTTP/1.1, 33.8%
* HTTP/2, 35.3%
* HTTP/3, 30.9%
To change http versions, use the `http_version` parameter.
import curl\_cffi
curl\_cffi.get("https://cloudflare-quic.com", http\_version\="v3")
Common values are: `v1`, `v2`, `v3` and `v3only`.
To get the actual used http version, you need to compare the response field with const from libcurl:
\>>> from curl\_cffi import CurlHttpVersion
\>>> r \= curl\_cffi.get("https://example.com", http\_version\="v2")
\>>> r.http\_version \== CurlHttpVersion.V2\_0
True
Keeping session alive in http/2[¶](https://curl-cffi.readthedocs.io/en/stable/advanced.html#keeping-session-alive-in-http-2 "Link to this heading")
----------------------------------------------------------------------------------------------------------------------------------------------------
With http/2, you can optionally send a ping frame to keep the connection alive when not actively using it.
import curl\_cffi
s \= Session()
s.get("https://example.com")
s.upkeep()
### [Table of Contents](https://curl-cffi.readthedocs.io/en/stable/index.html)
* [Advanced Topics](https://curl-cffi.readthedocs.io/en/stable/advanced.html#)
* [Proxies](https://curl-cffi.readthedocs.io/en/stable/advanced.html#proxies)
* [Low-level curl API](https://curl-cffi.readthedocs.io/en/stable/advanced.html#low-level-curl-api)
* [Using `CURLOPT_*` in requests API](https://curl-cffi.readthedocs.io/en/stable/advanced.html#using-curlopt-in-requests-api)
* [Selecting http version](https://curl-cffi.readthedocs.io/en/stable/advanced.html#selecting-http-version)
* [Keeping session alive in http/2](https://curl-cffi.readthedocs.io/en/stable/advanced.html#keeping-session-alive-in-http-2)
#### Previous topic
[Impersonation FAQ](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html "previous chapter")
#### Next topic
[Compatibility with requests](https://curl-cffi.readthedocs.io/en/stable/vs-requests.html "next chapter")
### This Page
* [Show Source](https://curl-cffi.readthedocs.io/en/stable/_sources/advanced.rst.txt)
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/vs-requests.html "Compatibility with requests")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html "Impersonation FAQ")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Advanced Topics](https://curl-cffi.readthedocs.io/en/stable/advanced.html)
---
# How to use my own fingerprints? e.g. okhttp — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/impersonate/psk.html "TLS PSK(41) Extension")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/impersonate/targets.html "Supported browser impersonate targets")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Impersonate Guide](https://curl-cffi.readthedocs.io/en/stable/impersonate/_index.html)
»
* [How to use my own fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/stable/impersonate/customize.html)
How to use my own fingerprints? e.g. okhttp[¶](https://curl-cffi.readthedocs.io/en/stable/impersonate/customize.html#how-to-use-my-own-fingerprints-e-g-okhttp "Link to this heading")
=======================================================================================================================================================================================
Use `ja3=...`, `akamai=...` and `extra_fp=...`.
You can retrieve the JA3 and Akamai strings using tools like WireShark or from TLS fingerprinting sites.
\# OKHTTP impersonatation examples
\# credits: https://github.com/bogdanfinn/tls-client/blob/master/profiles/contributed\_custom\_profiles.go
url \= "https://tls.browserleaks.com/json"
okhttp4\_android10\_ja3 \= ",".join(
\[\
"771",\
"4865-4866-4867-49195-49196-52393-49199-49200-52392-49171-49172-156-157-47-53",\
"0-23-65281-10-11-35-16-5-13-51-45-43-21",\
"29-23-24",\
"0",\
\]
)
okhttp4\_android10\_akamai \= "4:16777216|16711681|0|m,p,a,s"
extra\_fp \= {
"tls\_signature\_algorithms": \[\
"ecdsa\_secp256r1\_sha256",\
"rsa\_pss\_rsae\_sha256",\
"rsa\_pkcs1\_sha256",\
"ecdsa\_secp384r1\_sha384",\
"rsa\_pss\_rsae\_sha384",\
"rsa\_pkcs1\_sha384",\
"rsa\_pss\_rsae\_sha512",\
"rsa\_pkcs1\_sha512",\
"rsa\_pkcs1\_sha1",\
\]
\# other options:
\# tls\_min\_version: int = CurlSslVersion.TLSv1\_2
\# tls\_grease: bool = False
\# tls\_permute\_extensions: bool = False
\# tls\_cert\_compression: Literal\["zlib", "brotli"\] = "brotli"
\# tls\_signature\_algorithms: Optional\[List\[str\]\] = None
\# http2\_stream\_weight: int = 256
\# http2\_stream\_exclusive: int = 1
\# See requests/impersonate.py and tests/unittest/test\_impersonate.py for more examples
}
r \= curl\_cffi.get(
url, ja3\=okhttp4\_android10\_ja3, akamai\=okhttp4\_android10\_akamai, extra\_fp\=extra\_fp
)
print(r.json())
JA3 and Akamai String Format[¶](https://curl-cffi.readthedocs.io/en/stable/impersonate/customize.html#ja3-and-akamai-string-format "Link to this heading")
-----------------------------------------------------------------------------------------------------------------------------------------------------------
A JA3 string is a simple, comma-separated representation of the key fields in a TLS ClientHello. It consists of five parts:
* SSL/TLS Version, The numeric version the client requests (e.g. 771 for TLS 1.2).
* Cipher Suites, A hyphen-separated list of all cipher suite IDs offered by the client (e.g. 4865-4866-4867-49195-49196).
* Extension IDs, A hyphen-separated list of all TLS extension numbers the client includes (e.g. 0-11-10-35-16-5).
* Supported Groups (aka “Elliptic Curves”), A hyphen-separated list of curve IDs the client supports for ECDHE (e.g. 29-23-24).
* EC Point Formats, A hyphen-separated list of the point‐format IDs (almost always just 0 for “uncompressed”) (e.g. 0).
They’re concatenated in that exact order, with commas between fields. For example:
771,4865\-4866\-4867\-49195\-49196,0\-11\-10\-35\-16\-5,29\-23\-24,0
Note that Chrome permutes the extension order on each request, so there is a new format called JA3N, which uses sorted extension\_id list.
The Akamai HTTP/2 fingerprint string encodes four client‐controlled protocol parameters, joined by the pipe character (|):
* SETTINGS, A semicolon‐separated list of ID:value pairs from the client’s initial SETTINGS frame. Each ID is a standard HTTP/2 setting identifier (e.g. 1 for HEADER\_TABLE\_SIZE, 4 for INITIAL\_WINDOW\_SIZE), and value is the client’s chosen value for that setting
* WINDOW\_UPDATE, A single integer: the value the client sends in its first WINDOW\_UPDATE frame (or 0 if none was sent)
* PRIORITY, Zero or more priority‐frame tuples, each formatted as `StreamID:ExclusiveBit:DependentStreamID:Weight`. Multiple tuples are comma-separated. This captures any PRIORITY frames the client issues before sending headers
* Pseudo-Header Order, The sequence in which the client sends HTTP/2 pseudo-headers in its request HEADERS frame, encoded as comma-separated single-letter codes:
Putting it all together, an example fingerprint might look like:
1:65536;4:131072;5:16384|12517377|3:0:0:201|m,p,a,s
where:
SETTINGS \= 1:65536;4:131072;5:16384
WINDOW\_UPDATE \= 12517377
PRIORITY \= 3:0:0:201
Pseudo\-Header Order \= m,p,a,s
Although JA3 and Akamai fingerprint string already captures many of the aspects of a Hello Packet, there are still some fields are not covered and can be used to detect you. This is when the `extra_fp` option comes in, each field of this dict is pretty easy to understand. You should first set the ja3 and akamai string, then check if you have the identical fingerprint like your target. If not, use the `extra_fp` to further refine your impersonation.
Using CURLOPTs[¶](https://curl-cffi.readthedocs.io/en/stable/impersonate/customize.html#using-curlopts "Link to this heading")
-------------------------------------------------------------------------------------------------------------------------------
The other way is to use the `curlopt` s to specify exactly which options you want to change.
To modify them, use `curl.setopt(CurlOpt, value)`, for example:
import curl\_cffi
from curl\_cffi import Curl, CurlOpt
c \= Curl()
c.setopt(CurlOpt.HTTP2\_PSEUDO\_HEADERS\_ORDER, "masp")
\# or
curl\_cffi.get(url, curl\_options\={CurlOpt.HTTP2\_PSEUDO\_HEADERS\_ORDER, "masp"})
Here are a list of options:
For TLS/JA3 fingerprints:
* [https://curl.se/libcurl/c/CURLOPT\_SSL\_CIPHER\_LIST.html](https://curl.se/libcurl/c/CURLOPT_SSL_CIPHER_LIST.html)
and non-standard TLS options created for this project:
* `CURLOPT_SSL_ENABLE_ALPS`
* `CURLOPT_SSL_SIG_HASH_ALGS`
* `CURLOPT_SSL_CERT_COMPRESSION`
* `CURLOPT_SSL_ENABLE_TICKET`
* `CURLOPT_SSL_PERMUTE_EXTENSIONS`
For Akamai http2 fingerprints, you can fully customize the 3 parts:
* `CURLOPT_HTTP2_PSEUDO_HEADERS_ORDER`, sets http2 pseudo header order, for example: `masp` (non-standard HTTP/2 options created for this project).
* `CURLOPT_HTTP2_SETTINGS` sets the settings frame values, for example `1:65536;3:1000;4:6291456;6:262144` (non-standard HTTP/2 options created for this project).
* `CURLOPT_HTTP2_WINDOW_UPDATE` sets initial window update value for http2, for example `15663105` (non-standard HTTP/2 options created for this project).
For a complete list of options and explanation, see the [\`curl-impersoante README\`\_](https://curl-cffi.readthedocs.io/en/stable/impersonate/customize.html#id1)
.
How to toggle firefox-specific extensions?[¶](https://curl-cffi.readthedocs.io/en/stable/impersonate/customize.html#how-to-toggle-firefox-specific-extensions "Link to this heading")
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
There are a few special extensions from firefox that you should add extra options by `extra_fp`:
Extension 34: delegated credentials
extra\_fp \= {
"tls\_delegated\_credential": "ecdsa\_secp256r1\_sha256:ecdsa\_secp384r1\_sha384:ecdsa\_secp521r1\_sha512:ecdsa\_sha1"
}
\# Note that the ja3 string also includes extensiion: 34
ja3 \= "771,4865-4867-4866-49195-49199-52393-52392-49196-49200-49162-49161-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-34-18-51-43-13-45-28-27-65037,4588-29-23-24-25-256-257,0"
r \= curl\_cffi.get(url, ja3\=ja3, extra\_fp\=extra\_fp)
Extension 28: record size limit
extra\_fp \= {
"tls\_record\_size\_limit": 4001
}
\# Note that the ja3 string also includes extensiion: 28
ja3 \= "771,4865-4867-4866-49195-49199-52393-52392-49196-49200-49162-49161-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-5-34-18-51-43-13-45-28-27-65037,4588-29-23-24-25-256-257,0"
r \= curl\_cffi.get(url, ja3\=ja3, extra\_fp\=extra\_fp)
### [Table of Contents](https://curl-cffi.readthedocs.io/en/stable/index.html)
* [How to use my own fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/stable/impersonate/customize.html#)
* [JA3 and Akamai String Format](https://curl-cffi.readthedocs.io/en/stable/impersonate/customize.html#ja3-and-akamai-string-format)
* [Using CURLOPTs](https://curl-cffi.readthedocs.io/en/stable/impersonate/customize.html#using-curlopts)
* [How to toggle firefox-specific extensions?](https://curl-cffi.readthedocs.io/en/stable/impersonate/customize.html#how-to-toggle-firefox-specific-extensions)
#### Previous topic
[Supported browser impersonate targets](https://curl-cffi.readthedocs.io/en/stable/impersonate/targets.html "previous chapter")
#### Next topic
[TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/stable/impersonate/psk.html "next chapter")
### This Page
* [Show Source](https://curl-cffi.readthedocs.io/en/stable/_sources/impersonate/customize.rst.txt)
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/impersonate/psk.html "TLS PSK(41) Extension")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/impersonate/targets.html "Supported browser impersonate targets")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Impersonate Guide](https://curl-cffi.readthedocs.io/en/stable/impersonate/_index.html)
»
* [How to use my own fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/stable/impersonate/customize.html)
---
# Compatibility with requests — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/cookies.html "Cookies")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/advanced.html "Advanced Topics")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/stable/vs-requests.html)
Compatibility with requests[¶](https://curl-cffi.readthedocs.io/en/stable/vs-requests.html#compatibility-with-requests "Link to this heading")
===============================================================================================================================================
Although we try our best to mimic the requests API, some functionality is not easy to implement and left out. Here are a list of known incompatibilities:
* files API are slightly different, but more error-proof.
* retries are not supported yet, tracked in \[#24\]([https://github.com/lexiforest/curl\_cffi/issues/24](https://github.com/lexiforest/curl_cffi/issues/24)
)
* redirect history are not supported, tracked in \[#82\]([https://github.com/lexiforest/curl\_cffi/issues/82](https://github.com/lexiforest/curl_cffi/issues/82)
)
* empty-domains cookies may lost during redirects, tracked in \[#55\]([https://github.com/lexiforest/curl\_cffi/issues/55](https://github.com/lexiforest/curl_cffi/issues/55)
)
* response object can not be pickled.
* The `requests` proxies dict is supported, but we prefer `proxy=...`, unless you really use different proxies for http and https.
* You can use use transports/adapters, instead, you can use `curl_cffi` as adapter for `reuqests`.
Transports and Adapters[¶](https://curl-cffi.readthedocs.io/en/stable/vs-requests.html#transports-and-adapters "Link to this heading")
---------------------------------------------------------------------------------------------------------------------------------------
`curl_cffi` is deeply coupled with `libcurl-impersonate`. Unlike `requests` or `httpx`, There is no way to use a different networking library or mount different adapters.
Alternatively, you can use `curl-cffi` as a requests adapter via [curl-adapter](https://github.com/el1s7/curl-adapter)
. In this way, you get the full functionality of requests.
### [Table of Contents](https://curl-cffi.readthedocs.io/en/stable/index.html)
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/stable/vs-requests.html#)
* [Transports and Adapters](https://curl-cffi.readthedocs.io/en/stable/vs-requests.html#transports-and-adapters)
#### Previous topic
[Advanced Topics](https://curl-cffi.readthedocs.io/en/stable/advanced.html "previous chapter")
#### Next topic
[Cookies](https://curl-cffi.readthedocs.io/en/stable/cookies.html "next chapter")
### This Page
* [Show Source](https://curl-cffi.readthedocs.io/en/stable/_sources/vs-requests.rst.txt)
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/cookies.html "Cookies")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/advanced.html "Advanced Topics")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Compatibility with requests](https://curl-cffi.readthedocs.io/en/stable/vs-requests.html)
---
# Community — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/api.html "API References")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/cookies.html "Cookies")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Community](https://curl-cffi.readthedocs.io/en/stable/community.html)
Community[¶](https://curl-cffi.readthedocs.io/en/stable/community.html#community "Link to this heading")
=========================================================================================================
Scrapy integrations[¶](https://curl-cffi.readthedocs.io/en/stable/community.html#scrapy-integrations "Link to this heading")
-----------------------------------------------------------------------------------------------------------------------------
If you are using scrapy, check out these middlewares:
* \[divtiply/scrapy-curl-cffi\]([https://github.com/divtiply/scrapy-curl-cffi](https://github.com/divtiply/scrapy-curl-cffi)
)
* \[tieyongjie/scrapy-fingerprint\]([https://github.com/tieyongjie/scrapy-fingerprint](https://github.com/tieyongjie/scrapy-fingerprint)
)
* \[jxlil/scrapy-impersonate\]([https://github.com/jxlil/scrapy-impersonate](https://github.com/jxlil/scrapy-impersonate)
)
Using with eventlet/gevent[¶](https://curl-cffi.readthedocs.io/en/stable/community.html#using-with-eventlet-gevent "Link to this heading")
-------------------------------------------------------------------------------------------------------------------------------------------
Just set `thread` to eventlet or gevent.
from curl\_cffi import requests
s \= requests.Session(thread\="eventlet")
s.get(url)
As a urllib3/requests adapter[¶](https://curl-cffi.readthedocs.io/en/stable/community.html#as-a-urllib3-requests-adapter "Link to this heading")
-------------------------------------------------------------------------------------------------------------------------------------------------
You can also use curl-cffi as a requests adapter via [curl-adapter](https://github.com/el1s7/curl-adapter)
. In this way, you get the full functionality of requests.
import requests
from curl\_adapter import CurlCffiAdapter
session \= requests.Session()
session.mount("http://", CurlCffiAdapter())
session.mount("https://", CurlCffiAdapter())
\# just use requests session like you normally would
session.get("https://example.com")
As a httpx transport[¶](https://curl-cffi.readthedocs.io/en/stable/community.html#as-a-httpx-transport "Link to this heading")
-------------------------------------------------------------------------------------------------------------------------------
You can also use curl-cffi as a httpx transport via [httpx-curl-cffi](https://github.com/vgavro/httpx-curl-cffi)
. With this, you get the full functionality of httpx.
from httpx import Client, AsyncClient
from httpx\_curl\_cffi import CurlTransport, AsyncCurlTransport, CurlOpt
client \= Client(transport\=CurlTransport(impersonate\="chrome", default\_headers\=True))
client.get("https://tools.scrapfly.io/api/fp/ja3")
async\_client \= AsyncClient(transport\=AsyncCurlTransport(
impersonate\="chrome",
default\_headers\=True,
\# required for parallel requests, see curl\_cffi issues below
curl\_options\={CurlOpt.FRESH\_CONNECT: True}
))
### [Table of Contents](https://curl-cffi.readthedocs.io/en/stable/index.html)
* [Community](https://curl-cffi.readthedocs.io/en/stable/community.html#)
* [Scrapy integrations](https://curl-cffi.readthedocs.io/en/stable/community.html#scrapy-integrations)
* [Using with eventlet/gevent](https://curl-cffi.readthedocs.io/en/stable/community.html#using-with-eventlet-gevent)
* [As a urllib3/requests adapter](https://curl-cffi.readthedocs.io/en/stable/community.html#as-a-urllib3-requests-adapter)
* [As a httpx transport](https://curl-cffi.readthedocs.io/en/stable/community.html#as-a-httpx-transport)
#### Previous topic
[Cookies](https://curl-cffi.readthedocs.io/en/stable/cookies.html "previous chapter")
#### Next topic
[API References](https://curl-cffi.readthedocs.io/en/stable/api.html "next chapter")
### This Page
* [Show Source](https://curl-cffi.readthedocs.io/en/stable/_sources/community.rst.txt)
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/api.html "API References")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/cookies.html "Cookies")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Community](https://curl-cffi.readthedocs.io/en/stable/community.html)
---
# Cookies — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/community.html "Community")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/vs-requests.html "Compatibility with requests")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Cookies](https://curl-cffi.readthedocs.io/en/stable/cookies.html)
Cookies[¶](https://curl-cffi.readthedocs.io/en/stable/cookies.html#cookies "Link to this heading")
===================================================================================================
Save and load cookies[¶](https://curl-cffi.readthedocs.io/en/stable/cookies.html#save-and-load-cookies "Link to this heading")
-------------------------------------------------------------------------------------------------------------------------------
Do not use `get_dict` to dump and load cookies. Cookies are more than just plain key-value pairs.
Using pickle:
\# example from: https://github.com/encode/httpx/issues/895
import pickle
\# import httpx
import curl\_cffi
def save\_cookies(client):
with open("cookies.pk", "wb") as f:
pickle.dump(client.cookies.jar.\_cookies, f)
def load\_cookies():
if not os.path.isfile("cookies.pk"):
return None
with open("cookies.pk", "rb") as f:
return pickle.load(f)
\# client = httpx.Client(cookies=load\_cookies())
client \= curl\_cffi.Session()
client.get("https://httpbin.org/cookies/set/foo/bar")
save\_cookies(client)
client \= curl\_cffi.Session()
client.cookies.jar.\_cookies.update(load\_cookies())
print(client.cookies.get("foo"))
Using mozilla cookie jar:
See: [https://github.com/lexiforest/curl\_cffi/issues/381](https://github.com/lexiforest/curl_cffi/issues/381)
TODO: expose libcurl’s native cookies.txt support.
Discard cookies when using Session[¶](https://curl-cffi.readthedocs.io/en/stable/cookies.html#discard-cookies-when-using-session "Link to this heading")
---------------------------------------------------------------------------------------------------------------------------------------------------------
You may need to discard cookies when using sessions, especially when using `AsyncSession`.
Use the `discard_cookies` option.
s \= requests.Session()
set\_url \= "https://httpbin.org/cookies"
r \= s.get(set\_url)
assert r.cookies\["foo"\] \== s.cookies\["foo"\]
old\_cookie \= r.cookies\["foo"\]
\# Let's start discarding cookies
s.discard\_cookies \= True
r \= s.get(set\_url)
assert r.cookies\["foo"\] != s.cookies\["foo"\]
assert old\_cookie \== s.cookies\["foo"\]
\# The behavior can be reverted
s.discard\_cookies \= False
r \= s.get(set\_url)
assert r.cookies\["foo"\] \== s.cookies\["foo"\]
old\_cookie \= r.cookies\["foo"\]
\# Also works as request parameter
r \= s.get(set\_url, discard\_cookies\=True)
assert r.cookies\["foo"\] != s.cookies\["foo"\]
assert old\_cookie \== s.cookies\["foo"\]
### [Table of Contents](https://curl-cffi.readthedocs.io/en/stable/index.html)
* [Cookies](https://curl-cffi.readthedocs.io/en/stable/cookies.html#)
* [Save and load cookies](https://curl-cffi.readthedocs.io/en/stable/cookies.html#save-and-load-cookies)
* [Discard cookies when using Session](https://curl-cffi.readthedocs.io/en/stable/cookies.html#discard-cookies-when-using-session)
#### Previous topic
[Compatibility with requests](https://curl-cffi.readthedocs.io/en/stable/vs-requests.html "previous chapter")
#### Next topic
[Community](https://curl-cffi.readthedocs.io/en/stable/community.html "next chapter")
### This Page
* [Show Source](https://curl-cffi.readthedocs.io/en/stable/_sources/cookies.rst.txt)
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/community.html "Community")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/vs-requests.html "Compatibility with requests")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Cookies](https://curl-cffi.readthedocs.io/en/stable/cookies.html)
---
# FAQ — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/changelog.html "Change Log")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/api.html "API References")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [FAQ](https://curl-cffi.readthedocs.io/en/stable/faq.html)
FAQ[¶](https://curl-cffi.readthedocs.io/en/stable/faq.html#faq "Link to this heading")
=======================================================================================
What does the pro version offer? Is the open source project still maintained?[¶](https://curl-cffi.readthedocs.io/en/stable/faq.html#what-does-the-pro-version-offer-is-the-open-source-project-still-maintained "Link to this heading")
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Yes, the open source project is maintained as before.
In the [pro version](https://impersonate.pro/)
, we provide:
* weekly update of targets
* profiles for mobile browsers and apps
* some private detection fields
* http/3 fingerprints and proxy support
And, a better financial situation will help the open source version better maintained.
Why does the JA3 fingerprints change for Chrome 110+ impersonation?[¶](https://curl-cffi.readthedocs.io/en/stable/faq.html#why-does-the-ja3-fingerprints-change-for-chrome-110-impersonation "Link to this heading")
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
This is intended.
Chrome introduces `ClientHello` permutation in version 110, which means the order of extensions will be random, thus JA3 fingerprints will be random. So, when comparing JA3 fingerprints of `curl_cffi` and a browser, they may differ. However, this does not mean that TLS fingerprints will not be a problem, `ClientHello` extension order is just one factor of how servers can tell automated requests from browsers.
Roughly, this can be mitigated like:
ja3 \= md5(list(extensions), ...other arguments)
ja3n \= md5(set(extensions), ...other arguments)
See more from [this article](https://www.fastly.com/blog/a-first-look-at-chromes-tls-clienthello-permutation-in-the-wild)
and [curl-impersonate notes](https://github.com/lwthiker/curl-impersonate/pull/148)
.
Can I bypass Cloudflare with this project? or any other specific site.[¶](https://curl-cffi.readthedocs.io/en/stable/faq.html#can-i-bypass-cloudflare-with-this-project-or-any-other-specific-site "Link to this heading")
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Short answer is: it depends.
TLS and http2 fingerprints are just one of the many factors Cloudflare considers. Other factors include but are not limited to: IP quality, request rate, JS fingerprints, etc.
There are different protection levels for website owners to choose. For the most basic ones, TLS fingerprints alone maybe enough, but for higher levels, you may need to find a better proxy IP provider and use browser automation tools like playwright.
If you are in a hurry or just want the professionals to take care of the hard parts, you can consider the commercial solutions from our sponsors:
* [Yescaptcha](https://yescaptcha.com/i/stfnIO)
, captcha resolver and proxy service for bypassing Cloudflare.
* [ScrapeNinja](https://scrapeninja.net/?utm_source=github&utm_medium=banner&utm_campaign=cffi)
, Managed web scraping API.
For details, see the Sponsor section on front page.
I’m getting certs errors[¶](https://curl-cffi.readthedocs.io/en/stable/faq.html#i-m-getting-certs-errors "Link to this heading")
---------------------------------------------------------------------------------------------------------------------------------
The simplest way is to turn off cert verification by `verify=False`:
r \= curl\_cffi.get("https://example.com", verify\=False)
ErrCode: 77, Reason: error setting certificate verify locations[¶](https://curl-cffi.readthedocs.io/en/stable/faq.html#errcode-77-reason-error-setting-certificate-verify-locations "Link to this heading")
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
On Windows, if your Python environment or CA bundle path contains non-ASCII characters (e.g. accents), libcurl may fail to open the CA file when passed as a narrow `char*`. `curl_cffi` now encodes file-path options (e.g. `CAINFO`, `PROXY_CAINFO`, `SSLCERT`) using the system’s preferred ANSI code page on Windows to ensure correct file access. This fixes most occurrences of error 77.
How to use with fiddler/charles to intercept content[¶](https://curl-cffi.readthedocs.io/en/stable/faq.html#how-to-use-with-fiddler-charles-to-intercept-content "Link to this heading")
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Fiddler and Charles uses man-in-the-middle self-signed certs to intercept TLS traffic, to use with them, simply set `verify=False`.
ErrCode: 92, Reason: ‘HTTP/2 stream 0 was not closed cleanly: PROTOCOL\_ERROR (err 1)’[¶](https://curl-cffi.readthedocs.io/en/stable/faq.html#errcode-92-reason-http-2-stream-0-was-not-closed-cleanly-protocol-error-err-1 "Link to this heading")
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
This error(http/2 stream 0) has been reported many times ever since curl\_cffi was published, but I still can not find a reproducible way to trigger it. Given that the majority users are behind proxies, the situation is even more difficult to deal with.
I’m even not sure it’s a bug introduced in libcurl, curl-impersonate or curl\_cffi, or it’s just a server error. Depending on your context, here are some general suggestions for you:
* First, try removing the `Content-Length` header from you request.
* Try to see if this error was caused by proxies, if so, use better proxies.
* If it stops working after a while, maybe you’re just being blocked by, such as, Akamai.
* Force http/1.1 mode. Some websites’ h2 implementation is simply broken.
* See if the url works in your real browser.
* Find a stable way to reproduce it, so we can finally fix, or at least bypass it.
To force curl to use http 1.1 only.
import curl\_cffi
r \= curl\_cffi.get("https://postman-echo.com", http\_version\=curl\_cffi.CurlHttpVersion.V1\_1)
Related issues:
* [#19](https://github.com/lexiforest/curl_cffi/issues/19)
,
* [#42](https://github.com/lexiforest/curl_cffi/issues/42)
,
* [#79](https://github.com/lexiforest/curl_cffi/issues/79)
,
* [#165](https://github.com/lexiforest/curl_cffi/issues/165)
,
Packaging with PyInstaller[¶](https://curl-cffi.readthedocs.io/en/stable/faq.html#packaging-with-pyinstaller "Link to this heading")
-------------------------------------------------------------------------------------------------------------------------------------
If you encountered any issue with PyInstaller, here are a list of options provided by the community:
Add the `--hidden-import` option.
pyinstaller \-F .\\example.py \--hidden\-import\=\_cffi\_backend \--collect\-all curl\_cffi
Add other paths:
pyinstaller \--noconfirm \--onefile \--console \\
\--paths "C:/Users/Administrator/AppData/Local/Programs/Python/Python39" \\
\--add\-data "C:/Users/Administrator/AppData/Local/Programs/Python/Python39/Lib/site-packages/curl\_cffi.libs/libcurl-cbb416caa1dd01638554eab3f38d682d.dll;." \\
\--collect\-data "curl\_cffi" \\
"C:/Users/Administrator/Desktop/test\_script.py"
See also:
* [#5](https://github.com/lexiforest/curl_cffi/issues/5)
* [#48](https://github.com/lexiforest/curl_cffi/issues/48)
How to change the order of headers?[¶](https://curl-cffi.readthedocs.io/en/stable/faq.html#how-to-change-the-order-of-headers "Link to this heading")
------------------------------------------------------------------------------------------------------------------------------------------------------
By default, setting `impersonate` parameter will bring the corresponding headers. If you want to change the order or use your own headers, you need to turn off that and bring your own headers.
requests.get(url, impersonate\="chrome", default\_headers\=False, headers\=...)
How to deal with encoding/decoding errors?[¶](https://curl-cffi.readthedocs.io/en/stable/faq.html#how-to-deal-with-encoding-decoding-errors "Link to this heading")
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
Use `chardet` or `cchardet`
\>>> import curl\_cffi
\>>> r \= curl\_cffi.get("https://example.com/messy\_codec.html")
\>>> import chardet
\>>> chardet.detect(r.content)
{'encoding': 'GB2312', 'confidence': 0.99, 'language': 'Chinese'}
Or use regex or lxml to parse the meta header:
### [Table of Contents](https://curl-cffi.readthedocs.io/en/stable/index.html)
* [FAQ](https://curl-cffi.readthedocs.io/en/stable/faq.html#)
* [What does the pro version offer? Is the open source project still maintained?](https://curl-cffi.readthedocs.io/en/stable/faq.html#what-does-the-pro-version-offer-is-the-open-source-project-still-maintained)
* [Why does the JA3 fingerprints change for Chrome 110+ impersonation?](https://curl-cffi.readthedocs.io/en/stable/faq.html#why-does-the-ja3-fingerprints-change-for-chrome-110-impersonation)
* [Can I bypass Cloudflare with this project? or any other specific site.](https://curl-cffi.readthedocs.io/en/stable/faq.html#can-i-bypass-cloudflare-with-this-project-or-any-other-specific-site)
* [I’m getting certs errors](https://curl-cffi.readthedocs.io/en/stable/faq.html#i-m-getting-certs-errors)
* [ErrCode: 77, Reason: error setting certificate verify locations](https://curl-cffi.readthedocs.io/en/stable/faq.html#errcode-77-reason-error-setting-certificate-verify-locations)
* [How to use with fiddler/charles to intercept content](https://curl-cffi.readthedocs.io/en/stable/faq.html#how-to-use-with-fiddler-charles-to-intercept-content)
* [ErrCode: 92, Reason: ‘HTTP/2 stream 0 was not closed cleanly: PROTOCOL\_ERROR (err 1)’](https://curl-cffi.readthedocs.io/en/stable/faq.html#errcode-92-reason-http-2-stream-0-was-not-closed-cleanly-protocol-error-err-1)
* [Packaging with PyInstaller](https://curl-cffi.readthedocs.io/en/stable/faq.html#packaging-with-pyinstaller)
* [How to change the order of headers?](https://curl-cffi.readthedocs.io/en/stable/faq.html#how-to-change-the-order-of-headers)
* [How to deal with encoding/decoding errors?](https://curl-cffi.readthedocs.io/en/stable/faq.html#how-to-deal-with-encoding-decoding-errors)
#### Previous topic
[API References](https://curl-cffi.readthedocs.io/en/stable/api.html "previous chapter")
#### Next topic
[Change Log](https://curl-cffi.readthedocs.io/en/stable/changelog.html "next chapter")
### This Page
* [Show Source](https://curl-cffi.readthedocs.io/en/stable/_sources/faq.rst.txt)
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/changelog.html "Change Log")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/api.html "API References")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [FAQ](https://curl-cffi.readthedocs.io/en/stable/faq.html)
---
# TLS PSK(41) Extension — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html "Impersonation FAQ")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/impersonate/customize.html "How to use my own fingerprints? e.g. okhttp")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Impersonate Guide](https://curl-cffi.readthedocs.io/en/stable/impersonate/_index.html)
»
* [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/stable/impersonate/psk.html)
TLS PSK(41) Extension[¶](https://curl-cffi.readthedocs.io/en/stable/impersonate/psk.html#tls-psk-41-extension "Link to this heading")
======================================================================================================================================
What is the TLS PSK(41) extension, how to deal with it?
PSK is short for `Pre-Shared Key`, as defined in [RFC 8446](https://www.rfc-editor.org/rfc/rfc8446.html#section-2.2)
,
> Once a handshake has completed, the server can send the client a PSK identity that corresponds to a unique key derived from the initial handshake (see Section 4.6.1). The client can then use that PSK identity in future handshakes to negotiate the use of the associated PSK.
Usually, when you first visit a website, the PSK extension is not present in the extension list. But when you visit the same website for the second time, in a relatively short time, the client may offer a PSK extension with the key from the server.
For example, you can visit `https://tls.peet.ws/api/all`, and then refresh the page, the PSK extension will be there.
To correctly implement the PSK extension, the client must have some kind of a session cache held in memory or persisted on disk. All the major browsers have this feature for a very long time. `curl_cffi` added this feature in version `0.11.0`, with libcurl `8.13.0`.
The mechanism and behavior of a PSK looks like an http session cookie, where the server sent a cryptographic value as a key to resume a previous disconnected session. When the server generates a PSK, it is possible that the server keeps the mapping between the incoming IP and key. Thus, it can be problematic if you reuse a TLS session with rotating proxies.
┌───────────┐ ┌───────────┐
│ │ │ │
│ │ IP: 10.0.0.1 │ │
│ ┼─────────────TLS─Hello──────────────► │
│ │ │ │
│ ◄─────────────PSK:─xxx───────────────┼ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ Server │
│ Client │ IP: 10.0.0.2 │ │
│ ┼─────────────TLS─with─PSK───────────► │
│ │ │ │
│ ◄─────────────Blocked────────────────┼ │
│ │ │ │
│ │ PSK: xxx was │ │
│ │ associated with │ │
│ │ 10.0.0.1, not │ │
└───────────┘ 10.0.0.2 └───────────┘
Luckily, since curl\_cffi `0.12.0`, we added a new option called `proxy_credential_no_reuse`, when enabled, the TLS session cache will be bound based on the proxy username and IP, such that the session can only be reused when the proxy username and IP matches. From the server’s viewpoint, the `Pre-Shared Key` will be locked to the same source IP, not bouncing around among different exit nodes.
\# Python example to be added.
\# We might enable this by default when proxies are used.
How do I enable PSK extension anyway?[¶](https://curl-cffi.readthedocs.io/en/stable/impersonate/psk.html#how-do-i-enable-psk-extension-anyway "Link to this heading")
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
You don’t. If you haven’t, please read the explanation above first. Generally speaking, the client should manage this extension, and it should automatically offer this extension on the second request.
From the server’s perspective, if you forcefully add a PSK extension with random value, it’s an obvious sign that you are not a valid visitor, just like you providing an invalid cookie value.
However, it’s reasonable that you don’t want the PSK extension to be sent, i.e. pretending to be a first time visitor. We don’t support this for now, your option is to use an older version of curl\_cffi or create a new session on each request.
Note, some other impersonation-oriented http clients give you the control over adding the PSK or not, but you should let the client decide, if you are trying to impersonating browsers.
### [Table of Contents](https://curl-cffi.readthedocs.io/en/stable/index.html)
* [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/stable/impersonate/psk.html#)
* [How do I enable PSK extension anyway?](https://curl-cffi.readthedocs.io/en/stable/impersonate/psk.html#how-do-i-enable-psk-extension-anyway)
#### Previous topic
[How to use my own fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/stable/impersonate/customize.html "previous chapter")
#### Next topic
[Impersonation FAQ](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html "next chapter")
### This Page
* [Show Source](https://curl-cffi.readthedocs.io/en/stable/_sources/impersonate/psk.rst.txt)
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html "Impersonation FAQ")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/impersonate/customize.html "How to use my own fingerprints? e.g. okhttp")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Impersonate Guide](https://curl-cffi.readthedocs.io/en/stable/impersonate/_index.html)
»
* [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/stable/impersonate/psk.html)
---
# Development and contributing — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [previous](https://curl-cffi.readthedocs.io/en/stable/changelog.html "Change Log")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Development and contributing](https://curl-cffi.readthedocs.io/en/stable/dev.html)
Development and contributing[¶](https://curl-cffi.readthedocs.io/en/stable/dev.html#development-and-contributing "Link to this heading")
=========================================================================================================================================
This page documents how to compile curl-impersonate and curl-cffi from source. If binary package is not available on your platform, you may refer to this page for some inspirations.
First, you need to check if there are libcurl-impersonate binaries for you platform. If so, you can simply download and install them.
For now, a pre-compiled libcurl-impersonate is downloaded from github and built into a bdist wheel, which is a binary package format used by PyPI. However, the right way is to download curl and curl-impersonate sources on our side and compile them all together.
macOS
To install the local editable build:
\# This is for using the libcurl-impersonate built by GitHub actions
sudo mkdir /Users/runner
sudo chmod 777 /Users/runner
\# Dependencies
brew install libidn2 zstd
\# Then install
pip install \-e .\[test\]
pip install \-e .\[dev\]
Contributing[¶](https://curl-cffi.readthedocs.io/en/stable/dev.html#contributing "Link to this heading")
---------------------------------------------------------------------------------------------------------
When opening PR, please do not use the `main` branch in your fork, otherwise I cannot add my modification, such as unittests.
### [Table of Contents](https://curl-cffi.readthedocs.io/en/stable/index.html)
* [Development and contributing](https://curl-cffi.readthedocs.io/en/stable/dev.html#)
* [Contributing](https://curl-cffi.readthedocs.io/en/stable/dev.html#contributing)
#### Previous topic
[Change Log](https://curl-cffi.readthedocs.io/en/stable/changelog.html "previous chapter")
### This Page
* [Show Source](https://curl-cffi.readthedocs.io/en/stable/_sources/dev.rst.txt)
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [previous](https://curl-cffi.readthedocs.io/en/stable/changelog.html "Change Log")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Development and contributing](https://curl-cffi.readthedocs.io/en/stable/dev.html)
---
# Unknown
.. curl\_cffi documentation master file, created by sphinx-quickstart on Sat Feb 17 22:22:59 2024. You can adapt this file completely to your liking, but it should at least contain the root \`toctree\` directive. curl\_cffi's documentation ========================= .. toctree:: :maxdepth: 2 :caption: Contents: :glob: quick\_start impersonate/\_index advanced vs-requests cookies community api faq changelog dev \`Discuss on Telegram\`\_ .. \_Discuss on Telegram: https://t.me/+lL9n33eZp480MGM1 curl\_cffi is a Python binding for \`curl-impersonate fork\`\_ via \`cffi\`\_. For commercial support, visit \`impersonate.pro \`\_. .. \_curl-impersonate fork: https://github.com/lexiforest/curl-impersonate .. \_cffi: https://cffi.readthedocs.io/en/latest/ Unlike other pure Python http clients like \`\`httpx\`\` or \`\`requests\`\`, \`\`curl\_cffi\`\` can impersonate browsers' TLS signatures or JA3 fingerprints. If you are blocked by some website for no obvious reason, you can give this package a try. If you are looking for Python http3 clients, curl\_cffi added http3 support since \`\`v0.11\`\`. Sponsors -------- Bypass Cloudflare with API ~~~~~~~~~~~~~~~~~~~~~~~~~~ .. image:: https://raw.githubusercontent.com/lexiforest/curl\_cffi/main/assets/yescaptcha.png :width: 149 :alt: YesCaptcha :target: https://yescaptcha.com/i/stfnIO \`Yescaptcha \`\_ is a proxy service that bypasses Cloudflare and uses the API interface to obtain verified cookies (e.g. \`\`cf\_clearance\`\`). Click \`here \`\_ to register. You can also click \`here \`\_ to buy me a coffee. 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 \`\_. - Mimics 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 & 3.0, which requests does not. - Supports websocket. .. list-table:: Feature matrix :widths: 20 16 16 16 16 16 :header-rows: 1 \* - - requests - aiohttp - httpx - pycurl - curl\_cffi \* - http2 - ❌ - ❌ - ✅ - ✅ - ✅ \* - http3 - ❌ - ❌ - ❌ - ✅ - ✅ \* - sync - ✅ - ❌ - ✅ - ✅ - ✅ \* - async - ❌ - ✅ - ✅ - ❌ - ✅ \* - websocket - ❌ - ✅ - ❌ - ❌ - ✅ \* - fingerprints - ❌ - ❌ - ❌ - ❌ - ✅ \* - speed - 🐇 - 🐇🐇 - 🐇 - 🐇🐇 - 🐇🐇 Notes: 1. For pycurl, you need a http/3 enabled libcurl, while curl\_cffi packages libcurl-impersonate inside Python wheels. 2. Full http/3 supported was added in v0.12.0. Install ------- .. code-block:: sh pip install curl\_cffi --upgrade For more details, see :doc:\`quick\_start\`. Documentation ------------- You can first check out :doc:\`quick\_start\`. Then the :doc:\`impersonate\`. For advanced topics, checkout :doc:\`cookies\`, :doc:\`asyncio\` and :doc:\`websockets\`. You can also find common use cases in the \`examples \`\_ directory. Finally, if something is missing from the tutorial, you can always find them in the :doc:\`api\`. If you have any questions, be sure to check out the :doc:\`faq\` section before opening an issue. Indices and tables ================== \* :ref:\`genindex\` \* :ref:\`modindex\` \* :ref:\`search\`
---
# Search — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Search](https://curl-cffi.readthedocs.io/en/stable/search.html)
Search
======
Searching for multiple words only shows matches that contain all words.
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Search](https://curl-cffi.readthedocs.io/en/stable/search.html)
---
# Asyncio — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Asyncio](https://curl-cffi.readthedocs.io/en/stable/asyncio.html)
Asyncio[¶](https://curl-cffi.readthedocs.io/en/stable/asyncio.html#asyncio "Link to this heading")
===================================================================================================
TODO
### This Page
* [Show Source](https://curl-cffi.readthedocs.io/en/stable/_sources/asyncio.rst.txt)
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Asyncio](https://curl-cffi.readthedocs.io/en/stable/asyncio.html)
---
# WebSockets — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [WebSockets](https://curl-cffi.readthedocs.io/en/stable/websockets.html)
WebSockets[¶](https://curl-cffi.readthedocs.io/en/stable/websockets.html#websockets "Link to this heading")
============================================================================================================
TODO
### This Page
* [Show Source](https://curl-cffi.readthedocs.io/en/stable/_sources/websockets.rst.txt)
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [WebSockets](https://curl-cffi.readthedocs.io/en/stable/websockets.html)
---
# Change Log — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/dev.html "Development and contributing")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/faq.html "FAQ")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Change Log](https://curl-cffi.readthedocs.io/en/stable/changelog.html)
Change Log[¶](https://curl-cffi.readthedocs.io/en/stable/changelog.html#change-log "Link to this heading")
===========================================================================================================
Please see the [GitHub Releases](https://github.com/lexiforest/curl_cffi/releases)
page for details.
* v0.13
* Added support for Windows on Arm
* Improved support for websockets
* v0.12
* Added support for safari 26
* Improved support for websockets
* v0.11
* Added support for http3
* Added tor145, new safari and chrome targets
* v0.10.0
* Added support for using curl\_cffi directly
* v0.9.0
* Brought back Windows support
* Added support for Firefox
* Added support for Chrome 133a
* v0.8.0
* Added more recent impersonate versions, Safari 18.0 for iOS and macOS, Chrome 131.
* Added `quote` parameter for setting which letter should be quoted in URL.
* Added `response_class` parameter for using a customized `Response` class.
* v0.7.3
* Bugfixes.
* v0.7.2
* Added requests-like exception hierarchy.
* v0.7.1
* Added `Cookies.get_dict()`, for compatibility with `requests`.
* Fixed type conversion in C shim, by @qishipai.
* Fixed cookie `subdomains` attribute.
* v0.7.0
* Added more recent impersonate versions, up to Chrome 124.
* Upgraded `libcurl` to 8.7.1.
* Supported custom impersonation.
* Added support for list of tuple in post fields.
* Updated header strategy: always exclude empty headers, never send Expect header.
* Changed default redirect limit to 30.
* Prefer not sending CONNECT for plain http proxy.
* Fix Windows build.
* Fix Safari Stream priority.
The minimum Python version is now 3.8. Windows fingerprints are wrong in 0.6.x.
* v0.6.1
* `AsyncSession.close` is now a coroutine.
* This is a bugfix release.
* v0.6.0
* Added more recent impersonate versions, up to Chrome 120 and Safari 17.0
* Upgraded libcurl to 8.1.1
* Added experimental websocket support
* Supported proactive eventloop on Windows
* Added win32 and macOS arm64 build targets
* Added allow\_redirects to Session parameters
* Use certifi to replace packaged cacert.pem
* Improved proxy support by accepting proxy=…
* Bumped minimum python versiont to 3.8
* Added files support
* Added client certs support
* Incorporated build time files for sdist
* Bugfix: async curl timer leak
* v0.5.10
* Add stream support
* Add support for secure cookies
* Add curl\_infos to extract extra info after performing
* Bugfix: timeout=None not working
* v0.5.9
* Add interface support
* Make POST work as in real world
* Add support for custom resolve
* Switched to libcurl’s COOKIELIST to sync cookies between python and curl
* Add default\_headers option for sessions like in curl-impersonate
* Add curl\_options for extra curl\_options in Session
* Add http\_version option for limiting http version to 1.1 or whatever
* Add debug option for extra curl debug info
* Add CurlError.code
* Bugfix: duplicated header lines for the same header
* Bugfix: clearing headers when request fails
* Bugfix: fix HEAD request
* Bugfix: reset curl options when errors occur
* v0.5.7
* Refactor JSON serialization to mimic browser behavior (#66)
* Add http options to Session classes (#72)
* Add Windows eventloop warning
* v0.5.6
* Make Session.curl a thread-local variable (#50)
* Add support for eventlet and gevent with threadpool
* Bugfix: Only close future if it’s not done or cancelled
* 0.5.5
* Bugfix: Fix high CPU usage (#46)
* 0.5.4
* Bugfix: Fix cert and error buffer when calling curl\_easy\_reset
* 0.5.3
* Bugfix: Reset curl after performing, fix #39
* 0.5.2
* Bugfix: Clear headers after async perform
* 0.5.1
* Bugfix: Clean up timerfunction when curl already closed
* 0.5.0
* Added asyncio support
* 0.4.0
* Removed c shim callback function, use cffi native callback function
* 0.3.6
* Updated to curl-impersonate v0.5.4, supported chrome107 and chrome110
* 0.3.0, copied more code from httpx to support session
* Add requests.Session
* Breaking change: Response.cookies changed from http.cookies.SimpleCookie to curl\_cffi.requests.Cookies
* Using ABI3 wheels to reduce package size.
#### Previous topic
[FAQ](https://curl-cffi.readthedocs.io/en/stable/faq.html "previous chapter")
#### Next topic
[Development and contributing](https://curl-cffi.readthedocs.io/en/stable/dev.html "next chapter")
### This Page
* [Show Source](https://curl-cffi.readthedocs.io/en/stable/_sources/changelog.rst.txt)
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/dev.html "Development and contributing")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/faq.html "FAQ")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Change Log](https://curl-cffi.readthedocs.io/en/stable/changelog.html)
---
# Impersonation FAQ — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/advanced.html "Advanced Topics")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/impersonate/psk.html "TLS PSK(41) Extension")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Impersonate Guide](https://curl-cffi.readthedocs.io/en/stable/impersonate/_index.html)
»
* [Impersonation FAQ](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html)
Impersonation FAQ[¶](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html#impersonation-faq "Link to this heading")
===============================================================================================================================
How to check if my impersonation is working?[¶](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html#how-to-check-if-my-impersonation-is-working "Link to this heading")
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
The most reliable way is to use WireShark, and compare packets from `curl_cffi` and your targets.
If it’s challenging for you to use WireShark, you can use the following sites for JA3 and Akamai fingerprints:
1. [https://tls.browserleaks.com/json](https://tls.browserleaks.com/json)
2. [https://tls.peet.ws/api/all](https://tls.peet.ws/api/all)
3. [https://scrapfly.io/web-scraping-tools/browser-fingerprint](https://scrapfly.io/web-scraping-tools/browser-fingerprint)
For http/3 fingerprints, use our service:
1. [https://fp.impersonate.pro/api/http3](https://fp.impersonate.pro/api/http3)
I’m still being detected even if I impersonated correctly[¶](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html#i-m-still-being-detected-even-if-i-impersonated-correctly "Link to this heading")
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
First, JA3 and akamai fingerprints are not comprehensive, there are other fields that can be detected, we have a few more options listed in `extra_fp`. Be sure to also check them.
Note
Since `curl-impersonate` was posted on [Hacker News](https://news.ycombinator.com/item?id=42547820)
, some features and behaviors of `curl_cffi` is being detected by professional players. If we continue to fix these niche behavior in public, it would soon be noticed by those providers.
In short, if you are using curl\_cffi in production and you are sure about being blocked by TLS or http detection, try the [curl\_cffi pro version](https://impersonate.pro/)
.
Should I randomize my fingerprints for each request?[¶](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html#should-i-randomize-my-fingerprints-for-each-request "Link to this heading")
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
You can choose a random version from the list above, like:
random.choice(\["chrome119", "chrome120", ...\])
However, be aware of the browser market share, very old versions are not good choices.
Generally, you should not try to generate a customized random fingerprints. The reason is that, for a given browser version, the fingerprints are fixed. If you create a new random fingerprints, the server is easy to know that you are not using a typical browser.
If you were thinking about `ja3`, and not `ja3n`, then the fingerprints is already randomized, due to the `extension permutation` feature introduced in Chrome 110.
As far as we know, most websites use an allowlist, not a blocklist to filter out bot traffic. So do not expect random ja3 fingerprints would work in the wild.
Moreover, do not generate random ja3 strings. There are certain limits for a valid ja3 string. For example:
* TLS 1.3 ciphers must be at the front.
* GREASE extension must be the first.
* etc.
You should copy ja3 strings from sniffing tools, not generate them, unless you can make sure all the requirements are met.
Can I change JavaScript fingerprints with this library?[¶](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html#can-i-change-javascript-fingerprints-with-this-library "Link to this heading")
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
No, you can not. As the name suggests, JavaScript fingerprints are generated using JavaScript APIs provided by real browsers. `curl_cffi` is a python binding to a C library, with no browser or JavaScript runtime under the hood.
If you need to impersonate browsers on the JavaScript perspective, you can search for “Anti-detect Browser”, “Playwright stealth” and similar keywords. Or simply use a commercial plan from our sponsors.
Why are all the User-Agents macOS?[¶](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html#why-are-all-the-user-agents-macos "Link to this heading")
----------------------------------------------------------------------------------------------------------------------------------------------------------------
Simple, because I primarily use macOS and I copied the headers from my own browser. Fingerprints are generally the same across desktop OSes, if you want it to look like Windows, just update the user-agent and other related headers to Windows.
### [Table of Contents](https://curl-cffi.readthedocs.io/en/stable/index.html)
* [Impersonation FAQ](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html#)
* [How to check if my impersonation is working?](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html#how-to-check-if-my-impersonation-is-working)
* [I’m still being detected even if I impersonated correctly](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html#i-m-still-being-detected-even-if-i-impersonated-correctly)
* [Should I randomize my fingerprints for each request?](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html#should-i-randomize-my-fingerprints-for-each-request)
* [Can I change JavaScript fingerprints with this library?](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html#can-i-change-javascript-fingerprints-with-this-library)
* [Why are all the User-Agents macOS?](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html#why-are-all-the-user-agents-macos)
#### Previous topic
[TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/stable/impersonate/psk.html "previous chapter")
#### Next topic
[Advanced Topics](https://curl-cffi.readthedocs.io/en/stable/advanced.html "next chapter")
### This Page
* [Show Source](https://curl-cffi.readthedocs.io/en/stable/_sources/impersonate/faq.rst.txt)
### Quick search
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/advanced.html "Advanced Topics")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/impersonate/psk.html "TLS PSK(41) Extension")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [Impersonate Guide](https://curl-cffi.readthedocs.io/en/stable/impersonate/_index.html)
»
* [Impersonation FAQ](https://curl-cffi.readthedocs.io/en/stable/impersonate/faq.html)
---
# API References — curl_cffi documentation
### Navigation
* [index](https://curl-cffi.readthedocs.io/en/stable/genindex.html "General Index")
* [next](https://curl-cffi.readthedocs.io/en/stable/faq.html "FAQ")
|
* [previous](https://curl-cffi.readthedocs.io/en/stable/community.html "Community")
|
* [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/stable/index.html)
»
* [API References](https://curl-cffi.readthedocs.io/en/stable/api.html)
API References[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#api-references "Link to this heading")
=============================================================================================================
curl low levl APIs[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl-low-levl-apis "Link to this heading")
---------------------------------------------------------------------------------------------------------------------
### Curl[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl "Link to this heading")
class curl\_cffi.Curl(_cacert: str \= ''_, _debug: bool \= False_, _handle\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/curl.html#Curl)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl "Link to this definition")
Wrapper for `curl_easy_*` functions of libcurl.
\_\_init\_\_(_cacert: str \= ''_, _debug: bool \= False_, _handle\=None_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/curl.html#Curl.__init__)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.__init__ "Link to this definition")
Parameters:
* **cacert** – CA cert path to use, by default, certs from `certifi` are used.
* **debug** – whether to show curl debug messages.
* **handle** – a curl handle instance from `curl_easy_init`.
debug() → None[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/curl.html#Curl.debug)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.debug "Link to this definition")
Set debug to True
setopt(_option: [CurlOpt](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlOpt "curl_cffi.const.CurlOpt")
_, _value: Any_) → int[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/curl.html#Curl.setopt)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.setopt "Link to this definition")
Wrapper for `curl_easy_setopt`.
Parameters:
* **option** – option to set, using constants from CurlOpt enum
* **value** – value to set, strings will be handled automatically
Returns:
0 if no error, see `CurlECode`.
getinfo(_option: [CurlInfo](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlInfo "curl_cffi.const.CurlInfo")
_) → bytes | int | float | list[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/curl.html#Curl.getinfo)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.getinfo "Link to this definition")
Wrapper for `curl_easy_getinfo`. Gets information in response after curl.perform.
Parameters:
**option** – option to get info of, using constants from `CurlInfo` enum
Returns:
value retrieved from last perform.
version() → bytes[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/curl.html#Curl.version)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.version "Link to this definition")
Get the underlying libcurl version.
impersonate(_target: str_, _default\_headers: bool \= True_) → int[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/curl.html#Curl.impersonate)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.impersonate "Link to this definition")
Set the browser type to impersonate.
Parameters:
* **target** – browser to impersonate.
* **default\_headers** – whether to add default headers, like User-Agent.
Returns:
0 if no error.
perform(_clear\_headers: bool \= True_, _clear\_resolve: bool \= True_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/curl.html#Curl.perform)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.perform "Link to this definition")
Wrapper for `curl_easy_perform`, performs a curl request.
Parameters:
* **clear\_headers** – clear header slist used in this perform
* **clear\_resolve** – clear resolve slist used in this perform
Raises:
**CurlError** – if the perform was not successful.
duphandle() → [Curl](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl "curl_cffi.curl.Curl")
[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/curl.html#Curl.duphandle)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.duphandle "Link to this definition")
Wrapper for `curl_easy_duphandle`.
This is not a full copy of entire curl object in python. For example, headers handle is not copied, you have to set them again.
reset() → None[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/curl.html#Curl.reset)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.reset "Link to this definition")
Reset all curl options, wrapper for `curl_easy_reset`.
parse\_cookie\_headers(_headers: list\[bytes\]_) → SimpleCookie[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/curl.html#Curl.parse_cookie_headers)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.parse_cookie_headers "Link to this definition")
Extract `cookies.SimpleCookie` from header lines.
Parameters:
**headers** – list of headers in bytes.
Returns:
A parsed cookies.SimpleCookie instance.
static get\_reason\_phrase(_status\_line: bytes_) → bytes[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/curl.html#Curl.get_reason_phrase)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.get_reason_phrase "Link to this definition")
Extract reason phrase, like `OK`, `Not Found` from response status line.
static parse\_status\_line(_status\_line: bytes_) → tuple\[[CurlHttpVersion](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlHttpVersion "curl_cffi.const.CurlHttpVersion")\
, int, bytes\][\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/curl.html#Curl.parse_status_line)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.parse_status_line "Link to this definition")
Parse status line.
Returns:
http\_version, status\_code, and reason phrase
close() → None[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/curl.html#Curl.close)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.close "Link to this definition")
Close and cleanup curl handle, wrapper for `curl_easy_cleanup`.
ws\_recv() → tuple\[bytes, CurlWsFrame\][\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/curl.html#Curl.ws_recv)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.ws_recv "Link to this definition")
Receive a frame from a websocket connection.
Returns:
a tuple of frame content and curl frame meta struct.
Raises:
**CurlError** – if failed.
ws\_send(_payload: bytes_, _flags: [CurlWsFlag](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlWsFlag "curl_cffi.const.CurlWsFlag")
\= CurlWsFlag.BINARY_) → int[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/curl.html#Curl.ws_send)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.ws_send "Link to this definition")
Send data to a websocket connection.
Parameters:
* **payload** – content to send.
* **flags** – websocket flag to set for the frame, default: binary.
Returns:
0 if no error.
Raises:
**CurlError** – if failed.
ws\_close(_code: int \= 1000_, _message: bytes \= b''_) → int[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/curl.html#Curl.ws_close)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.ws_close "Link to this definition")
Close a websocket connection. Shorthand for [`ws_send()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.ws_send "curl_cffi.Curl.ws_send")
with close code and message. Note that to completely close the connection, you must close the curl handle after this call with [`close()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.close "curl_cffi.Curl.close")
.
Parameters:
* **code** – close code.
* **message** – close message.
Returns:
0 if no error.
Raises:
**CurlError** – if failed.
### AsyncCurl[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#asynccurl "Link to this heading")
class curl\_cffi.AsyncCurl(_cacert: str \= ''_, _loop\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/aio.html#AsyncCurl)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl "Link to this definition")
Wrapper around curl\_multi handle to provide asyncio support. It uses the libcurl socket\_action APIs.
\_\_init\_\_(_cacert: str \= ''_, _loop\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/aio.html#AsyncCurl.__init__)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.__init__ "Link to this definition")
Parameters:
* **cacert** – CA cert path to use, by default, certs from `certifi` are used.
* **loop** – EventLoop to use.
add\_handle(_curl: [Curl](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl "curl_cffi.curl.Curl")
_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/aio.html#AsyncCurl.add_handle)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.add_handle "Link to this definition")
Add a curl handle to be managed by curl\_multi. This is the equivalent of perform in the async world.
remove\_handle(_curl: [Curl](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl "curl_cffi.curl.Curl")
_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/aio.html#AsyncCurl.remove_handle)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.remove_handle "Link to this definition")
Cancel a future for given curl handle.
set\_result(_curl: [Curl](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl "curl_cffi.curl.Curl")
_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/aio.html#AsyncCurl.set_result)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.set_result "Link to this definition")
Mark a future as done for given curl handle.
set\_exception(_curl: [Curl](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl "curl_cffi.curl.Curl")
_, _exception_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/aio.html#AsyncCurl.set_exception)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.set_exception "Link to this definition")
Raise exception of a future for given curl handle.
setopt(_option_, _value_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/aio.html#AsyncCurl.setopt)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.setopt "Link to this definition")
Wrapper around curl\_multi\_setopt.
socket\_action(_sockfd: int_, _ev\_bitmask: int_) → int[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/aio.html#AsyncCurl.socket_action)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.socket_action "Link to this definition")
wrapper for curl\_multi\_socket\_action, returns the number of running curl handles.
process\_data(_sockfd: int_, _ev\_bitmask: int_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/aio.html#AsyncCurl.process_data)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.process_data "Link to this definition")
Call curl\_multi\_info\_read to read data for given socket.
async close()[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/aio.html#AsyncCurl.close)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.close "Link to this definition")
Close and cleanup running timers, readers, writers and handles.
### CurlMime[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curlmime "Link to this heading")
class curl\_cffi.CurlMime(_curl: [Curl](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl "curl_cffi.curl.Curl")
| None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/curl.html#CurlMime)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlMime "Link to this definition")
Wrapper for the `curl_mime_` API.
\_\_init\_\_(_curl: [Curl](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl "curl_cffi.curl.Curl")
| None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/curl.html#CurlMime.__init__)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlMime.__init__ "Link to this definition")
Parameters:
**curl** – Curl instance to use.
addpart(_name: str_, _\*_, _content\_type: str | None \= None_, _filename: str | None \= None_, _local\_path: str | bytes | Path | None \= None_, _data: bytes | None \= None_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/curl.html#CurlMime.addpart)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlMime.addpart "Link to this definition")
Add a mime part for a mutlipart html form.
Note: You can only use either local\_path or data, not both.
Parameters:
* **name** – name of the field.
* **content\_type** – content\_type for the field. for example: `image/png`.
* **filename** – filename for the server.
* **local\_path** – file to upload on local disk.
* **data** – file content to upload.
classmethod from\_list(_files: list\[dict\]_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/curl.html#CurlMime.from_list)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlMime.from_list "Link to this definition")
Create a multipart instance from a list of dict, for keys, see `addpart`
attach(_curl: [Curl](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl "curl_cffi.curl.Curl")
| None \= None_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/curl.html#CurlMime.attach)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlMime.attach "Link to this definition")
Attach the mime instance to a curl instance.
close() → None[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/curl.html#CurlMime.close)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlMime.close "Link to this definition")
Close the mime instance and underlying files. This method must be called after `perform` or `request`.
### Constants[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#constants "Link to this heading")
Enum values used by `setopt` and `getinfo` can be accessed from `CurlOpt` and `CurlInfo`.
class curl\_cffi.CurlOpt(_value_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/const.html#CurlOpt)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlOpt "Link to this definition")
`CULROPT_` constancs extracted from libcurl, see: [https://curl.se/libcurl/c/curl\_easy\_setopt.html](https://curl.se/libcurl/c/curl_easy_setopt.html)
class curl\_cffi.CurlInfo(_value_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/const.html#CurlInfo)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlInfo "Link to this definition")
`CURLINFO_` constancs extracted from libcurl, see: [https://curl.se/libcurl/c/curl\_easy\_getinfo.html](https://curl.se/libcurl/c/curl_easy_getinfo.html)
class curl\_cffi.CurlMOpt(_value_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/const.html#CurlMOpt)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlMOpt "Link to this definition")
`CURLMOPT_` constancs extracted from libcurl, see: [https://curl.se/libcurl/c/curl\_multi\_setopt.html](https://curl.se/libcurl/c/curl_multi_setopt.html)
class curl\_cffi.CurlECode(_value_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/const.html#CurlECode)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "Link to this definition")
`CURLECODE_` constancs extracted from libcurl, see: [https://curl.se/libcurl/c/libcurl-errors.html](https://curl.se/libcurl/c/libcurl-errors.html)
class curl\_cffi.CurlHttpVersion(_value_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/const.html#CurlHttpVersion)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlHttpVersion "Link to this definition")
`CURL_HTTP_VERSION` constants from libcurl, see comments for details.
class curl\_cffi.CurlWsFlag(_value_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/const.html#CurlWsFlag)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlWsFlag "Link to this definition")
`CURL_WS_FLAG` constants from libcurl, see comments for details.
class curl\_cffi.CurlSslVersion(_value_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/const.html#CurlSslVersion)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlSslVersion "Link to this definition")
`CURL_SSLVERSION` constants from libcurl, see comments for details.
requests-like API[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#requests-like-api "Link to this heading")
-------------------------------------------------------------------------------------------------------------------
### request method[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#request-method "Link to this heading")
`requests.get`, `requests.post`, etc are just aliases of `.request(METHOD, ...)`
curl\_cffi.requests.request(_method: Literal\['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD', 'TRACE', 'PATCH', 'QUERY'\]_, _url: str_, _thread: Literal\['eventlet', 'gevent'\] | None \= None_, _curl\_options: dict | None \= None_, _debug: bool | None \= None_, _\*\*kwargs: None_) → [Response](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response "curl_cffi.requests.models.Response")
[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests.html#request)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.request "Link to this definition")
Send an http request.
Parameters:
* **method** – http method for the request: GET/POST/PUT/DELETE etc.
* **url** – url for the requests.
* **params** – query string for the requests.
* **data** – form values(dict/list/tuple) or binary data to use in body, `Content-Type: application/x-www-form-urlencoded` will be added if a dict is given.
* **json** – json values to use in body, Content-Type: application/json will be added automatically.
* **headers** – headers to send.
* **cookies** – cookies to use.
* **files** – not supported, use `multipart` instead.
* **auth** – HTTP basic auth, a tuple of (username, password), only basic auth is supported.
* **timeout** – how many seconds to wait before giving up.
* **allow\_redirects** – whether to allow redirection.
* **max\_redirects** – max redirect counts, default 30, use -1 for unlimited.
* **proxies** – dict of proxies to use, prefer to use `proxy` if they are the same. format: `{"http": proxy_url, "https": proxy_url}`.
* **proxy** – proxy to use, format: “[http://user@pass:proxy\_url](http://user@pass:proxy_url)
”. Can’t be used with proxies parameter.
* **proxy\_auth** – HTTP basic auth for proxy, a tuple of (username, password).
* **verify** – whether to verify https certs.
* **referer** – shortcut for setting referer header.
* **accept\_encoding** – shortcut for setting accept-encoding header.
* **content\_callback** – a callback function to receive response body. `def callback(chunk: bytes) -> None:`
* **impersonate** – which browser version to impersonate.
* **ja3** – ja3 string to impersonate.
* **akamai** – akamai string to impersonate.
* **extra\_fp** – extra fingerprints options, in complement to ja3 and akamai strings.
* **thread** – thread engine to use for working with other thread implementations. choices: eventlet, gevent.
* **default\_headers** – whether to set default browser headers when impersonating.
* **default\_encoding** – encoding for decoding response content if charset is not found in headers. Defaults to “utf-8”. Can be set to a callable for automatic detection.
* **quote** – Set characters to be quoted, i.e. percent-encoded. Default safe string is `!#$%&'()*+,/:;=?@[]~`. If set to a sting, the character will be removed from the safe string, thus quoted. If set to False, the url will be kept as is, without any automatic percent-encoding, you must encode the URL yourself.
* **curl\_options** – extra curl options to use.
* **http\_version** – limiting http version, defaults to http2.
* **debug** – print extra curl debug info.
* **interface** – which interface to use.
* **cert** – a tuple of (cert, key) filenames for client cert.
* **stream** – streaming the response, default False.
* **max\_recv\_speed** – maximum receive speed, bytes per second.
* **multipart** – upload files using the multipart format, see examples for details.
* **discard\_cookies** – discard cookies from server. Default to False.
Returns:
A `Response` object.
### Sessions[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#sessions "Link to this heading")
class curl\_cffi.requests.Session(_curl: [Curl](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl "curl_cffi.Curl")
| None \= None_, _thread: ThreadType | None \= None_, _use\_thread\_local\_curl: bool \= True_, _\*\*kwargs: Unpack\[BaseSessionParams\[R\]\]_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/session.html#Session)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Session "Link to this definition")
A request session, cookies and connections will be reused. This object is thread-safe, but it’s recommended to use a separate session for each thread.
\_\_init\_\_(_curl: [Curl](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl "curl_cffi.Curl")
| None \= None_, _thread: ThreadType | None \= None_, _use\_thread\_local\_curl: bool \= True_, _\*\*kwargs: Unpack\[BaseSessionParams\[R\]\]_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/session.html#Session.__init__)
[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Session.__init__ "Link to this definition")
Parameters set in the `__init__` method will be overriden by the same parameter in request method.
Parameters:
* **curl** – curl object to use in the session. If not provided, a new one will be created. Also, a fresh curl object will always be created when accessed from another thread.
* **thread** – thread engine to use for working with other thread implementations. choices: eventlet, gevent.
* **headers** – headers to use in the session.
* **cookies** – cookies to add in the session.
* **auth** – HTTP basic auth, a tuple of (username, password), only basic auth is supported.
* **proxies** – dict of proxies to use, prefer to use proxy if they are the same. format: `{"http": proxy_url, "https": proxy_url}`.
* **proxy** – proxy to use, format: “[http://proxy\_url](http://proxy_url/)
”. Cannot be used with the above parameter.
* **proxy\_auth** – HTTP basic auth for proxy, a tuple of (username, password).
* **base\_url** – absolute url to use as base for relative urls.
* **params** – query string for the session.
* **verify** – whether to verify https certs.
* **timeout** – how many seconds to wait before giving up.
* **trust\_env** – use http\_proxy/https\_proxy and other environments, default True.
* **allow\_redirects** – whether to allow redirection.
* **max\_redirects** – max redirect counts, default 30, use -1 for unlimited.
* **impersonate** – which browser version to impersonate in the session.
* **ja3** – ja3 string to impersonate in the session.
* **akamai** – akamai string to impersonate in the session.
* **extra\_fp** – extra fingerprints options, in complement to ja3 and akamai str.
* **interface** – which interface use.
* **default\_encoding** – encoding for decoding response content if charset is not found in headers. Defaults to “utf-8”. Can be set to a callable for automatic detection.
* **cert** – a tuple of (cert, key) filenames for client cert.
* **response\_class** – A customized subtype of `Response` to use.
* **raise\_for\_status** – automatically raise an HTTPError for 4xx and 5xx status codes.
Notes
This class can be used as a context manager.
from curl\_cffi.requests import Session
with Session() as s:
r \= s.get("https://example.com")
request(_method: ~typing.Literal\['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD', 'TRACE', 'PATCH', 'QUERY'\], url: str, params: dict | list | tuple | None \= None, data: dict\[str, str\] | list\[tuple\] | str | ~io.BytesIO | bytes | None \= None, json: dict | list | None \= None, headers: ~curl\_cffi.requests.headers.Headers | ~collections.abc.Mapping\[str, str | None\] | ~collections.abc.Mapping\[bytes, bytes | None\] | ~collections.abc.Sequence\[tuple\[str, str\]\] | ~collections.abc.Sequence\[tuple\[bytes, bytes\]\] | ~collections.abc.Sequence\[str | bytes\] | None \= None, cookies: ~curl\_cffi.requests.cookies.Cookies | ~http.cookiejar.CookieJar | dict\[str, str\] | list\[tuple\[str, str\]\] | None \= None, files: dict | None \= None, auth: tuple\[str, str\] | None \= None, timeout: float | tuple\[float, float\] | object | None \=