# 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") [![YesCaptcha](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/yescaptcha.png)](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") [![Thordata](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/thordata.png)](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") [![YesCaptcha](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/yescaptcha.png)](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") [![YesCaptcha](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/yescaptcha.png)](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![¶](https://curl-cffi.readthedocs.io/en/v0.7.2/#welcome-to-curl-cffi-s-documentation "Link to this heading") =================================================================================================================================================== 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. * * * [![Scrapfly](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/scrapfly.png)](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") [![YesCaptcha](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/yescaptcha.png)](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") [![ScrapeNinja](https://scrapeninja.net/img/logo_with_text_new5.svg)](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![¶](https://curl-cffi.readthedocs.io/en/v0.7.1/#welcome-to-curl-cffi-s-documentation "Link to this heading") =================================================================================================================================================== 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. * * * [![Scrapfly](https://raw.githubusercontent.com/yifeikong/curl_cffi/main/assets/scrapfly.png)](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") [![YesCaptcha](https://raw.githubusercontent.com/yifeikong/curl_cffi/main/assets/yescaptcha.png)](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") [![ScrapeNinja](https://scrapeninja.net/img/logo_with_text_new5.svg)](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![¶](https://curl-cffi.readthedocs.io/en/v0.7.0/#welcome-to-curl-cffi-s-documentation "Link to this heading") =================================================================================================================================================== 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. * * * [![Scrapfly](https://raw.githubusercontent.com/yifeikong/curl_cffi/main/assets/scrapfly.png)](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") [![YesCaptcha](https://raw.githubusercontent.com/yifeikong/curl_cffi/main/assets/yescaptcha.png)](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") [![ScrapeNinja](https://scrapeninja.net/img/logo_with_text_new5.svg)](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![¶](https://curl-cffi.readthedocs.io/en/v0.11.0/#welcome-to-curl-cffi-s-documentation "Link to this heading") ==================================================================================================================================================== 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") [![SerpAPI](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/serpapi.png)](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") [![YesCaptcha](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/yescaptcha.png)](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") [![Capsolver](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/capsolver.jpg)](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![¶](https://curl-cffi.readthedocs.io/en/v0.11.2/#welcome-to-curl-cffi-s-documentation "Link to this heading") ==================================================================================================================================================== 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") [![SerpAPI](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/serpapi.png)](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") [![YesCaptcha](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/yescaptcha.png)](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") [![Capsolver](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/capsolver.jpg)](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![¶](https://curl-cffi.readthedocs.io/en/v0.10.0/#welcome-to-curl-cffi-s-documentation "Link to this heading") ==================================================================================================================================================== 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. * * * [![ProxyCurl](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/proxycurl.png)](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") [![YesCaptcha](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/yescaptcha.png)](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") [![ScrapeNinja](https://scrapeninja.net/img/logo_with_text_new5.svg)](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![¶](https://curl-cffi.readthedocs.io/en/v0.11.1/#welcome-to-curl-cffi-s-documentation "Link to this heading") ==================================================================================================================================================== 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") [![SerpAPI](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/serpapi.png)](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") [![YesCaptcha](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/yescaptcha.png)](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") [![Capsolver](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/capsolver.jpg)](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") [![SerpAPI](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/serpapi.png)](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") [![YesCaptcha](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/yescaptcha.png)](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") [![Capsolver](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/capsolver.jpg)](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") [![SerpAPI](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/serpapi.png)](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") [![YesCaptcha](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/yescaptcha.png)](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") [![Capsolver](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/capsolver.jpg)](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") [![YesCaptcha](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/yescaptcha.png)](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") [![SerpAPI](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/serpapi.png)](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") [![YesCaptcha](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/yescaptcha.png)](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") [![Capsolver](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/capsolver.jpg)](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![¶](https://curl-cffi.readthedocs.io/en/v0.6.3/#welcome-to-curl-cffi-s-documentation "Link to this heading") =================================================================================================================================================== 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. * * * [![Scrapfly](https://raw.githubusercontent.com/yifeikong/curl_cffi/main/assets/scrapfly.png)](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") [![YesCaptcha](https://raw.githubusercontent.com/yifeikong/curl_cffi/main/assets/yescaptcha.png)](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") [![ScrapeNinja](https://scrapeninja.net/img/logo_with_text_new5.svg)](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![¶](https://curl-cffi.readthedocs.io/en/v0.8.0/#welcome-to-curl-cffi-s-documentation "Link to this heading") =================================================================================================================================================== 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. * * * [![Scrapfly](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/scrapfly.png)](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") [![YesCaptcha](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/yescaptcha.png)](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") [![ScrapeNinja](https://scrapeninja.net/img/logo_with_text_new5.svg)](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![¶](https://curl-cffi.readthedocs.io/en/v0.6.1/#welcome-to-curl-cffi-s-documentation "Link to this heading") =================================================================================================================================================== 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") [![YesCaptcha](https://raw.githubusercontent.com/yifeikong/curl_cffi/main/assets/yescaptcha.png)](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") [![ScrapeNinja](https://scrapeninja.net/img/logo_with_text_new5.svg)](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![¶](https://curl-cffi.readthedocs.io/en/v0.6.2/#welcome-to-curl-cffi-s-documentation "Link to this heading") =================================================================================================================================================== 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") [![YesCaptcha](https://raw.githubusercontent.com/yifeikong/curl_cffi/main/assets/yescaptcha.png)](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") [![ScrapeNinja](https://scrapeninja.net/img/logo_with_text_new5.svg)](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![¶](https://curl-cffi.readthedocs.io/en/v0.6.0/#welcome-to-curl-cffi-s-documentation "Link to this heading") =================================================================================================================================================== 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") [![YesCaptcha](https://raw.githubusercontent.com/yifeikong/curl_cffi/main/assets/yescaptcha.png)](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") [![YesCaptcha](https://scrapeninja.net/img/logo_with_text_new5.svg)](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![¶](https://curl-cffi.readthedocs.io/en/v0.6.4/#welcome-to-curl-cffi-s-documentation "Link to this heading") =================================================================================================================================================== 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. * * * [![Scrapfly](https://raw.githubusercontent.com/yifeikong/curl_cffi/main/assets/scrapfly.png)](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") [![YesCaptcha](https://raw.githubusercontent.com/yifeikong/curl_cffi/main/assets/yescaptcha.png)](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") [![ScrapeNinja](https://scrapeninja.net/img/logo_with_text_new5.svg)](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![¶](https://curl-cffi.readthedocs.io/en/v0.9.0/#welcome-to-curl-cffi-s-documentation "Link to this heading") =================================================================================================================================================== 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. * * * [![ProxyCurl](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/proxycurl.png)](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") [![YesCaptcha](https://raw.githubusercontent.com/lexiforest/curl_cffi/main/assets/yescaptcha.png)](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") [![ScrapeNinja](https://scrapeninja.net/img/logo_with_text_new5.svg)](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__)

* [\_\_getitem\_\_() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies.__getitem__)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.__getitem__)

* [\_\_init\_\_() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.__init__)
* [(curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.__init__)

* [(curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlMime.__init__)

* [(curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncSession.__init__)

* [(curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.__init__)

* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Session.__init__)

* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.__init__) | * [\_\_setitem\_\_() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies.__setitem__)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.__setitem__) | A - | | | | --- | --- | | * [aclose() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.aclose)

* [acontent() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.acontent)

* [add\_handle() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.add_handle)

* [addpart() (curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlMime.addpart)

* [aiter\_content() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.aiter_content) | * [aiter\_lines() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.aiter_lines)

* [AsyncCurl (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl)

* [AsyncSession (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncSession)

* [AsyncWebSocket (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket)

* [atext() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.atext)

* [attach() (curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlMime.attach) | C - | | | | --- | --- | | * [CertificateVerifyError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.CertificateVerifyError)

* [charset (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.charset)

* [charset\_encoding (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.charset_encoding)

* [ChunkedEncodingError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.ChunkedEncodingError)

* [clear() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies.clear)

* [close() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.close)
* [(curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.close)

* [(curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlMime.close)

* [(curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncSession.close)

* [(curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.close)

* [(curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.close)

* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.close)

* [connect() (curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.connect)

* [ConnectionError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.ConnectionError) | * [ConnectTimeout (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.ConnectTimeout)

* [content (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.content)

* [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)

* [cookies (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.cookies)

* [Curl (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl)

* [CurlECode (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode)

* [CurlHttpVersion (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlHttpVersion)

* [CurlInfo (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlInfo)

* [CurlMime (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlMime)

* [CurlMOpt (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlMOpt)

* [CurlOpt (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlOpt)

* [CurlSslVersion (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlSslVersion)

* [CurlWsFlag (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlWsFlag) | D - | | | | --- | --- | | * [debug() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.debug)

* [default\_encoding (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.default_encoding)

* [delete() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies.delete) | * [DNSError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.DNSError)

* [download\_size (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.download_size)

* [duphandle() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.duphandle) | E - | | | | --- | --- | | * [elapsed (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.elapsed) | * [encoding (curl\_cffi.requests.Headers property)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.encoding)
* [(curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.encoding) | F - | | | | --- | --- | | * [FileModeWarning (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.FileModeWarning) | * [from\_list() (curl\_cffi.CurlMime class method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlMime.from_list) | G - | | | | --- | --- | | * [get() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies.get)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.get) | * [get\_list() (curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.get_list)

* [get\_reason\_phrase() (curl\_cffi.Curl static method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.get_reason_phrase)

* [getinfo() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.getinfo) | H - | | | | --- | --- | | * [header\_size (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.header_size)

* [Headers (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers)

* [headers (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.headers) | * [history (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.history)

* [http\_version (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.http_version)

* [HTTPError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.HTTPError) | I - | | | | --- | --- | | * [impersonate() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.impersonate)

* [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)

* [iter\_content() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.iter_content)

* [iter\_lines() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.iter_lines) | J - * [json() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.json) L - | | | | --- | --- | | * [local\_ip (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.local_ip) | * [local\_port (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.local_port) | M - | | | | --- | --- | | * [MissingSchema (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.MissingSchema) | * [multi\_items() (curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.multi_items) | O - * [ok (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.ok) P - | | | | --- | --- | | * [parse\_cookie\_headers() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.parse_cookie_headers)

* [parse\_status\_line() (curl\_cffi.Curl static method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.parse_status_line)

* [perform() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.perform)

* [ping() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.ping)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.ping) | * [primary\_ip (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.primary_ip)

* [primary\_port (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.primary_port)

* [process\_data() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.process_data)

* [ProxyError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.ProxyError) | R - | | | | --- | --- | | * [raise\_for\_status() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.raise_for_status)

* [raw() (curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.raw)

* [ReadTimeout (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.ReadTimeout)

* [reason (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.reason)

* [recv() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.recv)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.recv)

* [recv\_fragment() (curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.recv_fragment)

* [recv\_json() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.recv_json)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.recv_json)

* [recv\_str() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.recv_str)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.recv_str)

* [redirect\_count (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.redirect_count)

* [redirect\_url (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.redirect_url) | * [remove\_handle() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.remove_handle)

* [Request (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Request)

* [request() (curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncSession.request)
* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Session.request)

* [(in module curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.request)

* [request\_size (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.request_size)

* [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)

* [reset() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.reset)

* [Response (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response)

* [response\_size (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.response_size)

* [RetryError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.RetryError)

* [run\_forever() (curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.run_forever) | S - | | | | --- | --- | | * [send() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.send)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.send)

* [send\_binary() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.send_binary)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.send_binary)

* [send\_bytes() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.send_bytes)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.send_bytes)

* [send\_json() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.send_json)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.send_json)

* [send\_str() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.send_str)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.send_str)

* [Session (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Session) | * [SessionClosed (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.SessionClosed)

* [set() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies.set)

* [set\_exception() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.set_exception)

* [set\_result() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.set_result)

* [setopt() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.setopt)
* [(curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.setopt)

* [socket\_action() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.socket_action)

* [SSLError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.SSLError)

* [status\_code (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.status_code)

* [stream() (curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncSession.stream)
* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Session.stream)

* [StreamConsumedError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.StreamConsumedError) | T - | | | | --- | --- | | * [text (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.text) | * [Timeout (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.Timeout)

* [TooManyRedirects (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.TooManyRedirects) | U - | | | | --- | --- | | * [UnrewindableBodyError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.UnrewindableBodyError)

* [update() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies.update)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.update) | * [upload\_size (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.upload_size)

* [url (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.url)

* [URLRequired (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.URLRequired) | V - * [version() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.version) W - | | | | --- | --- | | * [WebSocket (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket)

* [ws\_close() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.ws_close)

* [ws\_connect() (curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncSession.ws_connect)
* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Session.ws_connect) | * [ws\_recv() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.ws_recv)

* [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 \= , allow\_redirects: bool | None \= None, max\_redirects: int | None \= None, proxies: dict\[str, str\] | None \= None, proxy: str | None \= None, proxy\_auth: tuple\[str, str\] | None \= None, verify: bool | None \= None, referer: str | None \= None, accept\_encoding: str | None \= 'gzip, deflate, br', content\_callback: ~collections.abc.Callable | None \= None, impersonate: ~typing.Literal\['edge99', 'edge101', 'chrome99', 'chrome100', 'chrome101', 'chrome104', 'chrome107', 'chrome110', 'chrome116', 'chrome119', 'chrome120', 'chrome123', 'chrome124', 'chrome131', 'chrome133a', 'chrome136', 'chrome142', 'chrome99\_android', 'chrome131\_android', 'safari153', 'safari155', 'safari170', 'safari172\_ios', 'safari180', 'safari180\_ios', 'safari184', 'safari184\_ios', 'safari260', 'safari2601', 'safari260\_ios', 'firefox133', 'firefox135', 'firefox144', 'tor145', 'chrome', 'edge', 'safari', 'safari\_ios', 'safari\_beta', 'safari\_ios\_beta', 'chrome\_android', 'firefox', 'safari15\_3', 'safari15\_5', 'safari17\_0', 'safari17\_2\_ios', 'safari18\_0', 'safari18\_0\_ios', 'safari18\_4', 'safari18\_4\_ios'\] | None \= None, ja3: str | None \= None, akamai: str | None \= None, extra\_fp: ~curl\_cffi.requests.impersonate.ExtraFingerprints | ~curl\_cffi.requests.impersonate.ExtraFpDict | None \= None, default\_headers: bool | None \= None, default\_encoding: str | ~collections.abc.Callable\[\[bytes\], str\] \= 'utf-8', quote: str | ~typing.Literal\[False\] \= '', http\_version: ~curl\_cffi.const.CurlHttpVersion | ~typing.Literal\['v1', 'v2', 'v2tls', 'v2\_prior\_knowledge', 'v3', 'v3only'\] | None \= None, interface: str | None \= None, cert: str | tuple\[str, str\] | None \= None, stream: bool | None \= None, max\_recv\_speed: int \= 0, multipart: ~curl\_cffi.curl.CurlMime | None \= None, discard\_cookies: bool \= False_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/session.html#Session.request) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Session.request "Link to this definition") Send the request, see `requests.request` for details on parameters. stream(_method: Literal\['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD', 'TRACE', 'PATCH', 'QUERY'\]_, _url: str_, _\*\*kwargs: None_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/session.html#Session.stream) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Session.stream "Link to this definition") Equivalent to `with request(..., stream=True) as r:` ws\_connect(_url_, _on\_message\=None_, _on\_error\=None_, _on\_open\=None_, _on\_close\=None_, _\*\*kwargs_) → [WebSocket](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket") [\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/session.html#Session.ws_connect) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Session.ws_connect "Link to this definition") Connects to a websocket url. Note: This method is deprecated, use WebSocket instead. Parameters: * **url** – the ws url to connect. * **on\_message** – message callback, `def on_message(ws, str)` * **on\_error** – error callback, `def on_error(ws, error)` * **on\_open** – open callback, `def on_open(ws)` * **on\_close** – close callback, `def on_close(ws)` Other parameters are the same as `.request` Returns: a WebSocket instance to communicate with the server. class curl\_cffi.requests.AsyncSession(_\*_, _loop\=None_, _async\_curl: [AsyncCurl](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl "curl_cffi.AsyncCurl") | None \= None_, _max\_clients: int \= 10_, _\*\*kwargs: Unpack\[BaseSessionParams\[R\]\]_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/session.html#AsyncSession) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncSession "Link to this definition") An async request session, cookies and connections will be reused. \_\_init\_\_(_\*_, _loop\=None_, _async\_curl: [AsyncCurl](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl "curl_cffi.AsyncCurl") | None \= None_, _max\_clients: int \= 10_, _\*\*kwargs: Unpack\[BaseSessionParams\[R\]\]_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/session.html#AsyncSession.__init__) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncSession.__init__ "Link to this definition") Parameters set in the `__init__` method will be override by the same parameter in request method. Parameters: * **loop** – loop to use, if not provided, the running loop will be used. * **async\_curl** – \[AsyncCurl\](/api/curl\_cffi#curl\_cffi.AsyncCurl) object to use. * **max\_clients** – maxmium curl handle to use in the session, this will affect the concurrency ratio. * **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 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. * **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, and it’s recommended to use via `async with`. However, unlike aiohttp, it is not required to use `with`. from curl\_cffi.requests import AsyncSession \# recommended. async with AsyncSession() as s: r \= await s.get("https://example.com") s \= AsyncSession() \# it also works. async 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 \= , allow\_redirects: bool | None \= None, max\_redirects: int | None \= None, proxies: dict\[str, str\] | None \= None, proxy: str | None \= None, proxy\_auth: tuple\[str, str\] | None \= None, verify: bool | None \= None, referer: str | None \= None, accept\_encoding: str | None \= 'gzip, deflate, br', content\_callback: ~collections.abc.Callable | None \= None, impersonate: ~typing.Literal\['edge99', 'edge101', 'chrome99', 'chrome100', 'chrome101', 'chrome104', 'chrome107', 'chrome110', 'chrome116', 'chrome119', 'chrome120', 'chrome123', 'chrome124', 'chrome131', 'chrome133a', 'chrome136', 'chrome142', 'chrome99\_android', 'chrome131\_android', 'safari153', 'safari155', 'safari170', 'safari172\_ios', 'safari180', 'safari180\_ios', 'safari184', 'safari184\_ios', 'safari260', 'safari2601', 'safari260\_ios', 'firefox133', 'firefox135', 'firefox144', 'tor145', 'chrome', 'edge', 'safari', 'safari\_ios', 'safari\_beta', 'safari\_ios\_beta', 'chrome\_android', 'firefox', 'safari15\_3', 'safari15\_5', 'safari17\_0', 'safari17\_2\_ios', 'safari18\_0', 'safari18\_0\_ios', 'safari18\_4', 'safari18\_4\_ios'\] | None \= None, ja3: str | None \= None, akamai: str | None \= None, extra\_fp: ~curl\_cffi.requests.impersonate.ExtraFingerprints | ~curl\_cffi.requests.impersonate.ExtraFpDict | None \= None, default\_headers: bool | None \= None, default\_encoding: str | ~collections.abc.Callable\[\[bytes\], str\] \= 'utf-8', quote: str | ~typing.Literal\[False\] \= '', http\_version: ~curl\_cffi.const.CurlHttpVersion | ~typing.Literal\['v1', 'v2', 'v2tls', 'v2\_prior\_knowledge', 'v3', 'v3only'\] | None \= None, interface: str | None \= None, cert: str | tuple\[str, str\] | None \= None, stream: bool | None \= None, max\_recv\_speed: int \= 0, multipart: ~curl\_cffi.curl.CurlMime | None \= None, discard\_cookies: bool \= False_) → R[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/session.html#AsyncSession.request) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncSession.request "Link to this definition") Send the request, see `curl_cffi.requests.request` for details on args. stream(_method: Literal\['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD', 'TRACE', 'PATCH', 'QUERY'\]_, _url: str_, _\*\*kwargs: None_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/session.html#AsyncSession.stream) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncSession.stream "Link to this definition") Equivalent to `async with request(..., stream=True) as r:` async close() → None[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/session.html#AsyncSession.close) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncSession.close "Link to this definition") Close the session. async ws\_connect(_url: str_, _autoclose: bool \= True_, _params: dict | list | tuple | None \= None_, _headers: 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: CookieJar | dict\[str_, _str\] | list\[tuple\[str_, _str\]\] | None\=None_, _auth: tuple\[str_, _str\] | None\=None_, _timeout: float | tuple\[float_, _float\] | object | None\=_, _allow\_redirects: bool | None \= None_, _max\_redirects: int | None \= None_, _proxies: dict\[str_, _str\] | None\=None_, _proxy: str | None \= None_, _proxy\_auth: tuple\[str_, _str\] | None\=None_, _verify: bool | None \= None_, _referer: str | None \= None_, _accept\_encoding: str | None \= 'gzip_, _deflate_, _br'_, _impersonate: Literal\['edge99'_, _'edge101'_, _'chrome99'_, _'chrome100'_, _'chrome101'_, _'chrome104'_, _'chrome107'_, _'chrome110'_, _'chrome116'_, _'chrome119'_, _'chrome120'_, _'chrome123'_, _'chrome124'_, _'chrome131'_, _'chrome133a'_, _'chrome136'_, _'chrome142'_, _'chrome99\_android'_, _'chrome131\_android'_, _'safari153'_, _'safari155'_, _'safari170'_, _'safari172\_ios'_, _'safari180'_, _'safari180\_ios'_, _'safari184'_, _'safari184\_ios'_, _'safari260'_, _'safari2601'_, _'safari260\_ios'_, _'firefox133'_, _'firefox135'_, _'firefox144'_, _'tor145'_, _'chrome'_, _'edge'_, _'safari'_, _'safari\_ios'_, _'safari\_beta'_, _'safari\_ios\_beta'_, _'chrome\_android'_, _'firefox'_, _'safari15\_3'_, _'safari15\_5'_, _'safari17\_0'_, _'safari17\_2\_ios'_, _'safari18\_0'_, _'safari18\_0\_ios'_, _'safari18\_4'_, _'safari18\_4\_ios'\] | None\=None_, _ja3: str | None \= None_, _akamai: str | None \= None_, _extra\_fp: ExtraFingerprints | ExtraFpDict | None \= None_, _default\_headers: bool | None \= None_, _quote: str | Literal\[False\] \= ''_, _http\_version: Literal\['v1'_, _'v2'_, _'v2tls'_, _'v2\_prior\_knowledge'_, _'v3'_, _'v3only'\] | None\=None_, _interface: str | None \= None_, _cert: str | tuple\[str_, _str\] | None\=None_, _max\_recv\_speed: int \= 0_, _recv\_queue\_size: int \= 512_, _send\_queue\_size: int \= 256_, _max\_send\_batch\_size: int \= 256_, _coalesce\_frames: bool \= False_, _retry\_on\_recv\_error: bool \= False_, _yield\_interval: float \= 0.001_, _fair\_scheduling: bool \= False_, _yield\_mask: int \= 63_) → [AsyncWebSocket](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket "curl_cffi.requests.websockets.AsyncWebSocket") [\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/session.html#AsyncSession.ws_connect) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncSession.ws_connect "Link to this definition") Connects to a WebSocket. Parameters: * **url** – url for the requests. * **autoclose** – whether to close the WebSocket after receiving a close frame. * **params** – query string for the requests. * **headers** – headers to send. * **cookies** – cookies to use. * **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. * **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 str. * **default\_headers** – whether to set default browser headers. * **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. * **interface** – which interface to use. * **cert** – a tuple of (cert, key) filenames for client cert. * **max\_recv\_speed** – maximum receive speed, bytes per second. * **recv\_queue\_size** – The maximum number of incoming WebSocket messages to buffer internally. This queue stores messages received by the Curl socket that are waiting to be consumed by calling recv(). * **send\_queue\_size** – The maximum number of outgoing WebSocket messages to buffer before applying network backpressure. When you call send(…) the message is placed in this queue and transmitted when the Curl socket is next available for sending. * **max\_send\_batch\_size** – The max batch size for sent frames. * **coalesce\_frames** – If True, multiple pending messages in the send queue may be merged into a single WebSocket frame for improved throughput. **Warning:** This breaks the one-to-one mapping of send() calls to frames and should only be used when the application protocol is designed to handle concatenated data streams. Defaults to False. * **retry\_on\_recv\_error** – Retries ws\_recv() if a recv error is raised. Retries up to a limited number of times with a delay in between. * **yield\_interval** – How often to yield control back to the event loop. This is a trade-off between throughput and responsiveness. Lower values means the loop yields more frequently and enables other tasks to run, while higher values are better for throughput. The balanced default is 1ms but you can customize this to fit your application/use case. * **fair\_scheduling** – Changes the I/O priority from favoring receives (5:1) to a balanced ratio (1:1). Enable this to improve send responsiveness under heavy, concurrent load, at the cost of significantly lower overall throughput. * **yield\_mask** – Controls the frequency of cooperative multitasking yields in the read loop. The loop yields every yield\_mask + 1 operations. For efficiency, this value must be a power of two minus one (e.g., 63, 127, 255). Lower values yield more often, improving fairness at the cost of throughput. Higher values yield less often, prioritizing throughput. ### Headers[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#headers "Link to this heading") class curl\_cffi.requests.Headers(_headers: [Headers](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers "curl_cffi.requests.headers.Headers") | Mapping\[str, str | None\] | Mapping\[bytes, bytes | None\] | Sequence\[tuple\[str, str\]\] | Sequence\[tuple\[bytes, bytes\]\] | Sequence\[str | bytes\] | None \= None_, _encoding: str | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/headers.html#Headers) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers "Link to this definition") HTTP headers, as a case-insensitive multi-dict. property encoding: str[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.encoding "Link to this definition") Header encoding is mandated as ascii, but we allow fallbacks to utf-8 or iso-8859-1. raw()[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.raw "Link to this definition") Returns a list of the raw header items, as byte pairs. multi\_items() → list\[tuple\[str, str | None\]\][\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/headers.html#Headers.multi_items) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.multi_items "Link to this definition") Return a list of (key, value) pairs of headers. Allow multiple occurrences of the same key without concatenating into a single comma separated value. get(_key: str_, _default: Any \= None_) → Any[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/headers.html#Headers.get) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.get "Link to this definition") Return a header value. If multiple occurrences of the header occur then concatenate them together with commas. get\_list(_key: str_, _split\_commas: bool \= False_) → list\[str | None\][\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/headers.html#Headers.get_list) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.get_list "Link to this definition") Return a list of all header values for a given key. If split\_commas=True is passed, then any comma separated header values are split into multiple return strings. update(\[_E_, \]_\*\*F_) → None.  Update D from mapping/iterable E and F.[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/headers.html#Headers.update) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.update "Link to this definition") If E present and has a .keys() method, does: for k in E: D\[k\] = E\[k\] If E present and lacks .keys() method, does: for (k, v) in E: D\[k\] = v In either case, this is followed by: for k, v in F.items(): D\[k\] = v \_\_getitem\_\_(_key: str_) → str | None[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/headers.html#Headers.__getitem__) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.__getitem__ "Link to this definition") Return a single header value. If there are multiple headers with the same key, then we concatenate them with commas. See: [https://tools.ietf.org/html/rfc7230#section-3.2.2](https://tools.ietf.org/html/rfc7230#section-3.2.2) \_\_setitem\_\_(_key: str_, _value: str | None_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/headers.html#Headers.__setitem__) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.__setitem__ "Link to this definition") Set the header key to value, removing any duplicate entries. Retains insertion order. \_\_delitem\_\_(_key: str_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/headers.html#Headers.__delitem__) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.__delitem__ "Link to this definition") Remove the header key. ### Cookies[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#cookies "Link to this heading") class curl\_cffi.requests.Cookies(_cookies: [Cookies](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies "curl_cffi.requests.cookies.Cookies") | CookieJar | dict\[str, str\] | list\[tuple\[str, str\]\] | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/cookies.html#Cookies) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies "Link to this definition") HTTP Cookies, as a mutable mapping. set(_name: str_, _value: str_, _domain: str \= ''_, _path: str \= '/'_, _secure\=False_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/cookies.html#Cookies.set) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies.set "Link to this definition") Set a cookie value by name. May optionally include domain and path. get(_name: str_, _default: str | None \= None_, _domain: str | None \= None_, _path: str | None \= None_) → str | None[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/cookies.html#Cookies.get) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies.get "Link to this definition") Get a cookie by name. May optionally include domain and path in order to specify exactly which cookie to retrieve. delete(_name: str_, _domain: str | None \= None_, _path: str | None \= None_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/cookies.html#Cookies.delete) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies.delete "Link to this definition") Delete a cookie by name. May optionally include domain and path in order to specify exactly which cookie to delete. clear(_domain: str | None \= None_, _path: str | None \= None_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/cookies.html#Cookies.clear) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies.clear "Link to this definition") Delete all cookies. Optionally include a domain and path in order to only delete a subset of all the cookies. update(\[_E_, \]_\*\*F_) → None.  Update D from mapping/iterable E and F.[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/cookies.html#Cookies.update) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies.update "Link to this definition") If E present and has a .keys() method, does: for k in E: D\[k\] = E\[k\] If E present and lacks .keys() method, does: for (k, v) in E: D\[k\] = v In either case, this is followed by: for k, v in F.items(): D\[k\] = v \_\_getitem\_\_(_name: str_) → str[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/cookies.html#Cookies.__getitem__) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies.__getitem__ "Link to this definition") \_\_setitem\_\_(_name: str_, _value: str_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/cookies.html#Cookies.__setitem__) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies.__setitem__ "Link to this definition") \_\_delitem\_\_(_name: str_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/cookies.html#Cookies.__delitem__) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies.__delitem__ "Link to this definition") ### Request, Response[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#request-response "Link to this heading") class curl\_cffi.requests.Request(_url: str_, _headers: [Headers](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers "curl_cffi.requests.headers.Headers") _, _method: str_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/models.html#Request) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Request "Link to this definition") Representing a sent request. class curl\_cffi.requests.Response(_curl: [Curl](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_, _request: [Request](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Request "curl_cffi.requests.models.Request") | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/models.html#Response) [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response "Link to this definition") Contains information the server sends. url[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.url "Link to this definition") url used in the request. content[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.content "Link to this definition") response body in bytes. text[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.text "Link to this definition") response body in str. status\_code[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.status_code "Link to this definition") http status code. reason[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.reason "Link to this definition") http response reason, such as OK, Not Found. ok[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.ok "Link to this definition") is status\_code in \[200, 400)?\ \ headers[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.headers "Link to this definition")\ \ response headers.\ \ cookies[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.cookies "Link to this definition")\ \ response cookies.\ \ elapsed[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.elapsed "Link to this definition")\ \ timedelta of the request duration.\ \ encoding[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.encoding "Link to this definition")\ \ http body encoding.\ \ charset[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.charset "Link to this definition")\ \ alias for encoding.\ \ primary\_ip[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.primary_ip "Link to this definition")\ \ primary ip of the server.\ \ primary\_port[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.primary_port "Link to this definition")\ \ primary port of the server.\ \ local\_ip[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.local_ip "Link to this definition")\ \ local ip used in this connection.\ \ local\_port[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.local_port "Link to this definition")\ \ local port used in this connection.\ \ charset\_encoding[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.charset_encoding "Link to this definition")\ \ encoding specified by the Content-Type header.\ \ default\_encoding[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.default_encoding "Link to this definition")\ \ 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.\ \ redirect\_count[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.redirect_count "Link to this definition")\ \ how many redirects happened.\ \ redirect\_url[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.redirect_url "Link to this definition")\ \ the final redirected url.\ \ http\_version[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.http_version "Link to this definition")\ \ http version used.\ \ history[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.history "Link to this definition")\ \ history redirections, only headers are available.\ \ download\_size[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.download_size "Link to this definition")\ \ total downloaded bytes (body).\ \ upload\_size[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.upload_size "Link to this definition")\ \ total uploaded bytes (body).\ \ header\_size[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.header_size "Link to this definition")\ \ total header size.\ \ request\_size[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.request_size "Link to this definition")\ \ request size.\ \ response\_size[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.response_size "Link to this definition")\ \ download\_size + header\_size\ \ raise\_for\_status()[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/models.html#Response.raise_for_status)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.raise_for_status "Link to this definition")\ \ Raise an error if status code is not in \[200, 400)\ \ iter\_lines(_chunk\_size\=None_, _decode\_unicode\=False_, _delimiter\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/models.html#Response.iter_lines)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.iter_lines "Link to this definition")\ \ iterate streaming content line by line, separated by `\n`.\ \ Copied from: [https://requests.readthedocs.io/en/latest/\_modules/requests/models/](https://requests.readthedocs.io/en/latest/_modules/requests/models/)\ which is under the License: Apache 2.0\ \ iter\_content(_chunk\_size\=None_, _decode\_unicode\=False_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/models.html#Response.iter_content)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.iter_content "Link to this definition")\ \ iterate streaming content chunk by chunk in bytes.\ \ json(_\*\*kw_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/models.html#Response.json)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.json "Link to this definition")\ \ return a parsed json object of the content.\ \ close()[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/models.html#Response.close)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.close "Link to this definition")\ \ Close the streaming connection, only valid in stream mode.\ \ async aiter\_lines(_chunk\_size\=None_, _decode\_unicode\=False_, _delimiter\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/models.html#Response.aiter_lines)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.aiter_lines "Link to this definition")\ \ iterate streaming content line by line, separated by `\n`.\ \ Copied from: [https://requests.readthedocs.io/en/latest/\_modules/requests/models/](https://requests.readthedocs.io/en/latest/_modules/requests/models/)\ which is under the License: Apache 2.0\ \ async aiter\_content(_chunk\_size\=None_, _decode\_unicode\=False_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/models.html#Response.aiter_content)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.aiter_content "Link to this definition")\ \ iterate streaming content chunk by chunk in bytes.\ \ async atext() → str[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/models.html#Response.atext)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.atext "Link to this definition")\ \ Return a decoded string.\ \ async acontent() → bytes[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/models.html#Response.acontent)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.acontent "Link to this definition")\ \ wait and read the streaming content in one bytes object.\ \ async aclose()[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/models.html#Response.aclose)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.aclose "Link to this definition")\ \ Close the streaming connection, only valid in stream mode.\ \ Asyncio[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#asyncio "Link to this heading")\ \ -----------------------------------------------------------------------------------------------\ \ WebSocket[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#websocket "Link to this heading")\ \ ---------------------------------------------------------------------------------------------------\ \ class curl\_cffi.requests.WebSocket(_curl: Union\[Curl_, _Any\]\=_, _\*_, _autoclose: bool \= True_, _skip\_utf8\_validation: bool \= False_, _debug: bool \= False_, _on\_open: ON\_OPEN\_T | None \= None_, _on\_close: ON\_CLOSE\_T | None \= None_, _on\_data: ON\_DATA\_T | None \= None_, _on\_message: ON\_MESSAGE\_T | None \= None_, _on\_error: ON\_ERROR\_T | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#WebSocket)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket "Link to this definition")\ \ A WebSocket implementation using libcurl.\ \ \_\_init\_\_(_curl: Union\[Curl_, _Any\]\=_, _\*_, _autoclose: bool \= True_, _skip\_utf8\_validation: bool \= False_, _debug: bool \= False_, _on\_open: ON\_OPEN\_T | None \= None_, _on\_close: ON\_CLOSE\_T | None \= None_, _on\_data: ON\_DATA\_T | None \= None_, _on\_message: ON\_MESSAGE\_T | None \= None_, _on\_error: ON\_ERROR\_T | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#WebSocket.__init__)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.__init__ "Link to this definition")\ \ Parameters:\ \ * **autoclose** – whether to close the WebSocket after receiving a close frame.\ \ * **skip\_utf8\_validation** – whether to skip UTF-8 validation for text frames in run\_forever().\ \ * **debug** – print extra curl debug info.\ \ * **on\_open** – open callback, `def on_open(ws)`\ \ * **on\_close** – close callback, `def on_close(ws, code, reason)`\ \ * **on\_data** – raw data receive callback, `def on_data(ws, data, frame)`\ \ * **on\_message** – message receive callback, `def on_message(ws, message)`\ \ * **on\_error** – error callback, `def on_error(ws, exception)`\ \ \ connect(_url: str, params: Optional\[Union\[dict, list, tuple\]\] \= None, headers: Optional\[HeaderTypes\] \= None, cookies: Optional\[CookieTypes\] \= None, auth: Optional\[tuple\[str, str\]\] \= None, timeout: Optional\[Union\[float, tuple\[float, float\], object\]\] \= , allow\_redirects: bool \= True, max\_redirects: int \= 30, proxies: Optional\[ProxySpec\] \= None, proxy: Optional\[str\] \= None, proxy\_auth: Optional\[tuple\[str, str\]\] \= None, verify: Optional\[bool\] \= None, referer: Optional\[str\] \= None, accept\_encoding: Optional\[str\] \= 'gzip, deflate, br', impersonate: Optional\[BrowserTypeLiteral\] \= None, ja3: Optional\[str\] \= None, akamai: Optional\[str\] \= None, extra\_fp: Optional\[Union\[ExtraFingerprints, ExtraFpDict\]\] \= None, default\_headers: bool \= True, quote: Union\[str, Literal\[False\]\] \= '', http\_version: Optional\[CurlHttpVersion\] \= None, interface: Optional\[str\] \= None, cert: Optional\[Union\[str, tuple\[str, str\]\]\] \= None, max\_recv\_speed: int \= 0, curl\_options: Optional\[dict\[CurlOpt, str\]\] \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#WebSocket.connect)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.connect "Link to this definition")\ \ Connect to the WebSocket.\ \ libcurl automatically handles pings and pongs. ref: [https://curl.se/libcurl/c/libcurl-ws.html](https://curl.se/libcurl/c/libcurl-ws.html)\ \ Parameters:\ \ * **url** – url for the requests.\ \ * **params** – query string for the requests.\ \ * **headers** – headers to send.\ \ * **cookies** – cookies to use.\ \ * **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.\ \ * **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 str.\ \ * **default\_headers** – whether to set default browser headers.\ \ * **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.\ \ * **interface** – which interface to use.\ \ * **cert** – a tuple of (cert, key) filenames for client cert.\ \ * **max\_recv\_speed** – maximum receive speed, bytes per second.\ \ * **curl\_options** – extra curl options to use.\ \ \ recv\_fragment() → tuple\[bytes, CurlWsFrame\][\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#WebSocket.recv_fragment)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.recv_fragment "Link to this definition")\ \ Receive a single curl websocket fragment as bytes.\ \ recv() → tuple\[bytes, int\][\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#WebSocket.recv)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.recv "Link to this definition")\ \ Receive a frame as bytes. libcurl splits frames into fragments, so we have to collect all the chunks for a frame.\ \ recv\_str() → str[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#WebSocket.recv_str)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.recv_str "Link to this definition")\ \ Receive a text frame.\ \ recv\_json(_\*, loads: Callable\[\[str\], T\] \= _) → T[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#WebSocket.recv_json)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.recv_json "Link to this definition")\ \ Receive a JSON frame.\ \ Parameters:\ \ **loads** – JSON decoder, default is json.loads.\ \ send(_payload: str | bytes | memoryview_, _flags: [CurlWsFlag](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlWsFlag "curl_cffi.const.CurlWsFlag")\ \= CurlWsFlag.BINARY_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#WebSocket.send)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.send "Link to this definition")\ \ Send a data frame.\ \ Parameters:\ \ * **payload** – data to send.\ \ * **flags** – flags for the frame.\ \ \ send\_binary(_payload: bytes_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#WebSocket.send_binary)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.send_binary "Link to this definition")\ \ Send a binary frame.\ \ Parameters:\ \ **payload** – binary data to send.\ \ send\_bytes(_payload: bytes_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#WebSocket.send_bytes)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.send_bytes "Link to this definition")\ \ Send a binary frame, alias of [`send_binary()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.send_binary "curl_cffi.requests.WebSocket.send_binary")\ .\ \ Parameters:\ \ **payload** – binary data to send.\ \ send\_str(_payload: str_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#WebSocket.send_str)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.send_str "Link to this definition")\ \ Send a text frame.\ \ Parameters:\ \ **payload** – text data to send.\ \ send\_json(_payload: ~typing.Any, \*, dumps: ~collections.abc.Callable\[\[~typing.Any\], str\] \= functools.partial(, separators=(',', ':'))_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#WebSocket.send_json)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.send_json "Link to this definition")\ \ Send a JSON frame.\ \ Parameters:\ \ * **payload** – data to send.\ \ * **dumps** – JSON encoder, default is json.dumps.\ \ \ ping(_payload: str | bytes_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#WebSocket.ping)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.ping "Link to this definition")\ \ Send a ping frame.\ \ Parameters:\ \ **payload** – data to send.\ \ run\_forever(_url: str \= ''_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#WebSocket.run_forever)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.run_forever "Link to this definition")\ \ Run the WebSocket forever. See [`connect()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.connect "curl_cffi.requests.WebSocket.connect")\ for details on parameters.\ \ libcurl automatically handles pings and pongs. ref: [https://curl.se/libcurl/c/libcurl-ws.html](https://curl.se/libcurl/c/libcurl-ws.html)\ \ close(_code: int \= WsCloseCode.OK_, _message: bytes \= b''_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#WebSocket.close)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.close "Link to this definition")\ \ Close the connection.\ \ Parameters:\ \ * **code** – close code.\ \ * **message** – close reason.\ \ \ class curl\_cffi.requests.AsyncWebSocket(_session: [AsyncSession](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncSession "curl_cffi.requests.AsyncSession")\ _, _curl: [Curl](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl "curl_cffi.Curl")\ _, _\*_, _autoclose: bool \= True_, _debug: bool \= False_, _recv\_queue\_size: int \= 512_, _send\_queue\_size: int \= 256_, _max\_send\_batch\_size: int \= 256_, _coalesce\_frames: bool \= False_, _retry\_on\_recv\_error: bool \= False_, _yield\_interval: float \= 0.001_, _fair\_scheduling: bool \= False_, _yield\_mask: int \= 63_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket "Link to this definition")\ \ An asyncio WebSocket implementation using libcurl.\ \ NOTE: This object represents a single WebSocket connection. Once closed, it cannot be reopened. A new instance must be created to reconnect.\ \ \_\_init\_\_(_session: [AsyncSession](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncSession "curl_cffi.requests.AsyncSession")\ _, _curl: [Curl](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl "curl_cffi.Curl")\ _, _\*_, _autoclose: bool \= True_, _debug: bool \= False_, _recv\_queue\_size: int \= 512_, _send\_queue\_size: int \= 256_, _max\_send\_batch\_size: int \= 256_, _coalesce\_frames: bool \= False_, _retry\_on\_recv\_error: bool \= False_, _yield\_interval: float \= 0.001_, _fair\_scheduling: bool \= False_, _yield\_mask: int \= 63_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.__init__)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.__init__ "Link to this definition")\ \ Initializes an Async WebSocket session.\ \ This class should not be instantiated directly. It is intended to be created via the AsyncSession.ws\_connect() method, which correctly handles setup and initialization of the underlying I/O tasks.\ \ Important\ \ This WebSocket implementation uses a decoupled I/O model. Network operations occur in background tasks. As a result, network-related errors that occur during a send() operation will not be raised by send(). Instead, they are placed into the receive queue and will be raised by the next call to recv().\ \ Parameters:\ \ * **session** ([_AsyncSession_](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncSession "curl_cffi.requests.AsyncSession")\ ) – An instantiated AsyncSession object.\ \ * **curl** ([_Curl_](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl "curl_cffi.Curl")\ ) – The underlying Curl to use.\ \ * **autoclose** (_bool__,_ _optional_) – Close the WS on receiving a close frame.\ \ * **debug** (_bool__,_ _optional_) – Enable debug messages. Defaults to False.\ \ * **recv\_queue\_size** (_int__,_ _optional_) – The maximum number of incoming WebSocket messages to buffer internally. This queue stores messages received by the Curl socket that are waiting to be consumed by calling recv()\ \ * **send\_queue\_size** (_int__,_ _optional_) – The maximum number of outgoing WebSocket messages to buffer before applying network backpressure. When you call send(…) the message is placed in this queue and transmitted when the Curl socket is next available for sending.\ \ * **max\_send\_batch\_size** (_int__,_ _optional_) – The max number of messages per batch.\ \ * **coalesce\_frames** (_bool__,_ _optional_) – Combine multiple frames into a batch.\ \ * **retry\_on\_recv\_error** (_bool__,_ _optional_) – Retry recv on some transient errors.\ \ * **yield\_interval** (_float__,_ _optional_) – How often to yield control in seconds.\ \ * **fair\_scheduling** (_bool__,_ _optional_) – Change the ~5:1 ratio in favor of recv:send to a fairer 1:1 ratio. This decreases recv throughput.\ \ * **yield\_mask** (_int__,_ _optional_) – A bitmask that sets the yield frequency for cooperative multitasking, checked every yield\_mask + 1 operations. Must be a power of two minus one (e.g., 63, 127, 255) for efficient bitwise checks. Lower values increase fairness; higher values increase throughput.\ \ \ async recv(_\*_, _timeout: float | None \= None_) → tuple\[bytes | None, int\][\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.recv)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.recv "Link to this definition")\ \ Receive a frame as bytes.\ \ This method waits for and returns the next complete data frame from the receive queue.\ \ Parameters:\ \ **timeout** – how many seconds to wait before giving up.\ \ Raises:\ \ * **WebSocketClosed** – If recv() is called on a closed connection after the receive queue is empty.\ \ * **WebSocketTimeout** – If the operation times out.\ \ * **WebSocketError** – A protocol or network error that occurred in a background I/O task, including errors from previous send() operations.\ \ \ Returns:\ \ A tuple with the received payload and flags.\ \ Return type:\ \ tuple\[bytes, int\]\ \ async recv\_str(_\*_, _timeout: float | None \= None_) → str[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.recv_str)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.recv_str "Link to this definition")\ \ Receive a text frame.\ \ Parameters:\ \ **timeout** – how many seconds to wait before giving up.\ \ async recv\_json(_\*, loads: Callable\[\[Union\[str, bytes\]\], T\] \= , timeout: Optional\[float\] \= None_) → T[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.recv_json)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.recv_json "Link to this definition")\ \ Receive a JSON frame.\ \ Parameters:\ \ * **loads** – JSON decoder, default is json.loads.\ \ * **timeout** – how many seconds to wait before giving up.\ \ \ async send(_payload: str | bytes | bytearray | memoryview_, _flags: [CurlWsFlag](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlWsFlag "curl_cffi.const.CurlWsFlag")\ \= CurlWsFlag.BINARY_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.send)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.send "Link to this definition")\ \ Send a data frame.\ \ This method is a lightweight, non-blocking call that places the payload into a send queue. The actual network transmission is handled by a background task.\ \ To guarantee all your messages have been sent await ws.flush(…).\ \ The max frame size supported by libcurl is 65535 bytes. Larger frames will be broken down and sent in chunks of that size.\ \ Parameters:\ \ * **payload** – data to send.\ \ * **flags** – flags for the frame.\ \ \ Raises:\ \ **WebSocketClosed** – The WebSocket is closed.\ \ Note\ \ Due to the asynchronous nature of this client, network errors (e.g., connection dropped) that occur during the actual transmission will NOT be raised by this method. They will be raised by a subsequent call to recv(). Always ensure you are actively receiving data to handle potential connection errors.\ \ Also: If the network is slow and the internal send queue becomes full, this method will block until there is space in the queue.\ \ async send\_binary(_payload: bytes_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.send_binary)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.send_binary "Link to this definition")\ \ Send a binary frame.\ \ Parameters:\ \ **payload** – binary data to send.\ \ For more info, see the docstring for send(…)\ \ async send\_bytes(_payload: bytes_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.send_bytes)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.send_bytes "Link to this definition")\ \ Send a binary frame, alias of [`send_binary()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.send_binary "curl_cffi.requests.AsyncWebSocket.send_binary")\ .\ \ Parameters:\ \ **payload** – binary data to send.\ \ For more info, see the docstring for send(…)\ \ async send\_str(_payload: str_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.send_str)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.send_str "Link to this definition")\ \ Send a text frame.\ \ Parameters:\ \ **payload** – text data to send.\ \ For more info, see the docstring for send(…)\ \ async send\_json(_payload: ~typing.Any, \*, dumps: ~collections.abc.Callable\[\[~typing.Any\], str\] \= functools.partial(, separators=(',', ':'))_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.send_json)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.send_json "Link to this definition")\ \ Send a JSON frame.\ \ Parameters:\ \ * **payload** – data to send.\ \ * **dumps** – JSON encoder, default is json.dumps(…).\ \ \ For more info, see the docstring for send(…)\ \ async ping(_payload: str | bytes_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.ping)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.ping "Link to this definition")\ \ Send a ping frame.\ \ Parameters:\ \ **payload** – data to send.\ \ For more info, see the docstring for send(…)\ \ async close(_code: int \= WsCloseCode.OK_, _message: bytes \= b''_, _timeout: float \= 5.0_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.close)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.close "Link to this definition")\ \ Performs a graceful WebSocket closing handshake and terminates the connection.\ \ This method sends a WebSocket close frame to the peer, waits for queued outgoing messages to be sent, and then shuts down the connection. This is the recommended way to close the session.\ \ Parameters:\ \ * **code** (_int__,_ _optional_) – Close code. Defaults to WsCloseCode.OK.\ \ * **message** (_bytes__,_ _optional_) – Close reason. Defaults to b””.\ \ * **timeout** (_float__,_ _optional_) – How long in seconds to wait closed.\ \ \ Exceptions and Warnings[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#exceptions-and-warnings "Link to this heading")\ \ -------------------------------------------------------------------------------------------------------------------------------\ \ ### Exceptions[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#exceptions "Link to this heading")\ \ We try to follow the requests exception hirearchy, however, some are missing, while some are added.\ \ If an exception is marked as “not used”, please catch the base exception.\ \ class curl\_cffi.requests.exceptions.RequestException(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#RequestException)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.RequestException "Link to this definition")\ \ Base exception for curl\_cffi.requests package\ \ class curl\_cffi.requests.exceptions.CookieConflict(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#CookieConflict)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.CookieConflict "Link to this definition")\ \ Same cookie exists for different domains.\ \ class curl\_cffi.requests.exceptions.SessionClosed(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#SessionClosed)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.SessionClosed "Link to this definition")\ \ The session has already been closed.\ \ class curl\_cffi.requests.exceptions.ImpersonateError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#ImpersonateError)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.ImpersonateError "Link to this definition")\ \ The impersonate config was wrong or impersonate failed.\ \ class curl\_cffi.requests.exceptions.InvalidJSONError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#InvalidJSONError)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.InvalidJSONError "Link to this definition")\ \ A JSON error occurred. not used\ \ class curl\_cffi.requests.exceptions.HTTPError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#HTTPError)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.HTTPError "Link to this definition")\ \ An HTTP error occurred.\ \ class curl\_cffi.requests.exceptions.IncompleteRead(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#IncompleteRead)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.IncompleteRead "Link to this definition")\ \ Incomplete read of content\ \ class curl\_cffi.requests.exceptions.ConnectionError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#ConnectionError)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.ConnectionError "Link to this definition")\ \ A Connection error occurred.\ \ class curl\_cffi.requests.exceptions.DNSError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#DNSError)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.DNSError "Link to this definition")\ \ Could not resolve\ \ class curl\_cffi.requests.exceptions.ProxyError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#ProxyError)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.ProxyError "Link to this definition")\ \ A proxy error occurred.\ \ class curl\_cffi.requests.exceptions.SSLError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#SSLError)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.SSLError "Link to this definition")\ \ An SSL error occurred.\ \ class curl\_cffi.requests.exceptions.CertificateVerifyError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#CertificateVerifyError)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.CertificateVerifyError "Link to this definition")\ \ Raised when certificate validated has failed\ \ class curl\_cffi.requests.exceptions.Timeout(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#Timeout)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.Timeout "Link to this definition")\ \ The request timed out.\ \ class curl\_cffi.requests.exceptions.ConnectTimeout(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#ConnectTimeout)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.ConnectTimeout "Link to this definition")\ \ The request timed out while trying to connect to the remote server.\ \ Requests that produced this error are safe to retry.\ \ not used\ \ class curl\_cffi.requests.exceptions.ReadTimeout(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#ReadTimeout)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.ReadTimeout "Link to this definition")\ \ The server did not send any data in the allotted amount of time. not used\ \ class curl\_cffi.requests.exceptions.URLRequired(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#URLRequired)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.URLRequired "Link to this definition")\ \ A valid URL is required to make a request. not used\ \ class curl\_cffi.requests.exceptions.TooManyRedirects(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#TooManyRedirects)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.TooManyRedirects "Link to this definition")\ \ Too many redirects.\ \ class curl\_cffi.requests.exceptions.MissingSchema(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#MissingSchema)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.MissingSchema "Link to this definition")\ \ The URL scheme (e.g. http or https) is missing. not used\ \ class curl\_cffi.requests.exceptions.InvalidSchema(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#InvalidSchema)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.InvalidSchema "Link to this definition")\ \ The URL scheme provided is either invalid or unsupported. not used\ \ class curl\_cffi.requests.exceptions.InvalidURL(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#InvalidURL)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.InvalidURL "Link to this definition")\ \ The URL provided was somehow invalid.\ \ class curl\_cffi.requests.exceptions.InvalidHeader(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#InvalidHeader)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.InvalidHeader "Link to this definition")\ \ The header value provided was somehow invalid. not used\ \ class curl\_cffi.requests.exceptions.InvalidProxyURL(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#InvalidProxyURL)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.InvalidProxyURL "Link to this definition")\ \ The proxy URL provided is invalid. not used\ \ class curl\_cffi.requests.exceptions.ChunkedEncodingError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#ChunkedEncodingError)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.ChunkedEncodingError "Link to this definition")\ \ The server declared chunked encoding but sent an invalid chunk. not used\ \ class curl\_cffi.requests.exceptions.ContentDecodingError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#ContentDecodingError)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.ContentDecodingError "Link to this definition")\ \ Failed to decode response content. not used\ \ class curl\_cffi.requests.exceptions.StreamConsumedError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#StreamConsumedError)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.StreamConsumedError "Link to this definition")\ \ The content for this response was already consumed. not used\ \ class curl\_cffi.requests.exceptions.RetryError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#RetryError)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.RetryError "Link to this definition")\ \ Custom retries logic failed. not used\ \ class curl\_cffi.requests.exceptions.UnrewindableBodyError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#UnrewindableBodyError)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.UnrewindableBodyError "Link to this definition")\ \ Requests encountered an error when trying to rewind a body. not used\ \ class curl\_cffi.requests.exceptions.InterfaceError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#InterfaceError)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.InterfaceError "Link to this definition")\ \ A specified outgoing interface could not be used.\ \ ### Warnings[¶](https://curl-cffi.readthedocs.io/en/stable/api.html#warnings "Link to this heading")\ \ class curl\_cffi.requests.exceptions.RequestsWarning[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#RequestsWarning)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.RequestsWarning "Link to this definition")\ \ Base warning for Requests. not used\ \ class curl\_cffi.requests.exceptions.FileModeWarning[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#FileModeWarning)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.FileModeWarning "Link to this definition")\ \ A file was opened in text mode, but Requests determined its binary length. not used\ \ class curl\_cffi.requests.exceptions.RequestsDependencyWarning[\[source\]](https://curl-cffi.readthedocs.io/en/stable/_modules/curl_cffi/requests/exceptions.html#RequestsDependencyWarning)\ [¶](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.RequestsDependencyWarning "Link to this definition")\ \ An imported dependency doesn’t match the expected version range.\ \ ### [Table of Contents](https://curl-cffi.readthedocs.io/en/stable/index.html)\ \ * [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)\ * [Curl](https://curl-cffi.readthedocs.io/en/stable/api.html#curl)\ * [`Curl`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl)\ * [`Curl.__init__()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.__init__)\ \ * [`Curl.debug()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.debug)\ \ * [`Curl.setopt()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.setopt)\ \ * [`Curl.getinfo()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.getinfo)\ \ * [`Curl.version()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.version)\ \ * [`Curl.impersonate()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.impersonate)\ \ * [`Curl.perform()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.perform)\ \ * [`Curl.duphandle()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.duphandle)\ \ * [`Curl.reset()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.reset)\ \ * [`Curl.parse_cookie_headers()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.parse_cookie_headers)\ \ * [`Curl.get_reason_phrase()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.get_reason_phrase)\ \ * [`Curl.parse_status_line()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.parse_status_line)\ \ * [`Curl.close()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.close)\ \ * [`Curl.ws_recv()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.ws_recv)\ \ * [`Curl.ws_send()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.ws_send)\ \ * [`Curl.ws_close()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.Curl.ws_close)\ \ * [AsyncCurl](https://curl-cffi.readthedocs.io/en/stable/api.html#asynccurl)\ * [`AsyncCurl`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl)\ * [`AsyncCurl.__init__()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.__init__)\ \ * [`AsyncCurl.add_handle()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.add_handle)\ \ * [`AsyncCurl.remove_handle()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.remove_handle)\ \ * [`AsyncCurl.set_result()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.set_result)\ \ * [`AsyncCurl.set_exception()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.set_exception)\ \ * [`AsyncCurl.setopt()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.setopt)\ \ * [`AsyncCurl.socket_action()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.socket_action)\ \ * [`AsyncCurl.process_data()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.process_data)\ \ * [`AsyncCurl.close()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.AsyncCurl.close)\ \ * [CurlMime](https://curl-cffi.readthedocs.io/en/stable/api.html#curlmime)\ * [`CurlMime`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlMime)\ * [`CurlMime.__init__()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlMime.__init__)\ \ * [`CurlMime.addpart()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlMime.addpart)\ \ * [`CurlMime.from_list()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlMime.from_list)\ \ * [`CurlMime.attach()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlMime.attach)\ \ * [`CurlMime.close()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlMime.close)\ \ * [Constants](https://curl-cffi.readthedocs.io/en/stable/api.html#constants)\ * [`CurlOpt`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlOpt)\ \ * [`CurlInfo`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlInfo)\ \ * [`CurlMOpt`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlMOpt)\ \ * [`CurlECode`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlECode)\ \ * [`CurlHttpVersion`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlHttpVersion)\ \ * [`CurlWsFlag`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlWsFlag)\ \ * [`CurlSslVersion`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.CurlSslVersion)\ \ * [requests-like API](https://curl-cffi.readthedocs.io/en/stable/api.html#requests-like-api)\ * [request method](https://curl-cffi.readthedocs.io/en/stable/api.html#request-method)\ * [`request()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.request)\ \ * [Sessions](https://curl-cffi.readthedocs.io/en/stable/api.html#sessions)\ * [`Session`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Session)\ * [`Session.__init__()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Session.__init__)\ \ * [`Session.request()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Session.request)\ \ * [`Session.stream()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Session.stream)\ \ * [`Session.ws_connect()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Session.ws_connect)\ \ * [`AsyncSession`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncSession)\ * [`AsyncSession.__init__()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncSession.__init__)\ \ * [`AsyncSession.request()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncSession.request)\ \ * [`AsyncSession.stream()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncSession.stream)\ \ * [`AsyncSession.close()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncSession.close)\ \ * [`AsyncSession.ws_connect()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncSession.ws_connect)\ \ * [Headers](https://curl-cffi.readthedocs.io/en/stable/api.html#headers)\ * [`Headers`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers)\ * [`Headers.encoding`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.encoding)\ \ * [`Headers.raw()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.raw)\ \ * [`Headers.multi_items()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.multi_items)\ \ * [`Headers.get()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.get)\ \ * [`Headers.get_list()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.get_list)\ \ * [`Headers.update()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.update)\ \ * [`Headers.__getitem__()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.__getitem__)\ \ * [`Headers.__setitem__()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.__setitem__)\ \ * [`Headers.__delitem__()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Headers.__delitem__)\ \ * [Cookies](https://curl-cffi.readthedocs.io/en/stable/api.html#cookies)\ * [`Cookies`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies)\ * [`Cookies.set()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies.set)\ \ * [`Cookies.get()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies.get)\ \ * [`Cookies.delete()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies.delete)\ \ * [`Cookies.clear()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies.clear)\ \ * [`Cookies.update()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies.update)\ \ * [`Cookies.__getitem__()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies.__getitem__)\ \ * [`Cookies.__setitem__()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies.__setitem__)\ \ * [`Cookies.__delitem__()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Cookies.__delitem__)\ \ * [Request, Response](https://curl-cffi.readthedocs.io/en/stable/api.html#request-response)\ * [`Request`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Request)\ \ * [`Response`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response)\ * [`Response.url`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.url)\ \ * [`Response.content`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.content)\ \ * [`Response.text`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.text)\ \ * [`Response.status_code`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.status_code)\ \ * [`Response.reason`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.reason)\ \ * [`Response.ok`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.ok)\ \ * [`Response.headers`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.headers)\ \ * [`Response.cookies`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.cookies)\ \ * [`Response.elapsed`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.elapsed)\ \ * [`Response.encoding`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.encoding)\ \ * [`Response.charset`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.charset)\ \ * [`Response.primary_ip`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.primary_ip)\ \ * [`Response.primary_port`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.primary_port)\ \ * [`Response.local_ip`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.local_ip)\ \ * [`Response.local_port`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.local_port)\ \ * [`Response.charset_encoding`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.charset_encoding)\ \ * [`Response.default_encoding`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.default_encoding)\ \ * [`Response.redirect_count`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.redirect_count)\ \ * [`Response.redirect_url`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.redirect_url)\ \ * [`Response.http_version`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.http_version)\ \ * [`Response.history`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.history)\ \ * [`Response.download_size`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.download_size)\ \ * [`Response.upload_size`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.upload_size)\ \ * [`Response.header_size`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.header_size)\ \ * [`Response.request_size`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.request_size)\ \ * [`Response.response_size`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.response_size)\ \ * [`Response.raise_for_status()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.raise_for_status)\ \ * [`Response.iter_lines()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.iter_lines)\ \ * [`Response.iter_content()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.iter_content)\ \ * [`Response.json()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.json)\ \ * [`Response.close()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.close)\ \ * [`Response.aiter_lines()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.aiter_lines)\ \ * [`Response.aiter_content()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.aiter_content)\ \ * [`Response.atext()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.atext)\ \ * [`Response.acontent()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.acontent)\ \ * [`Response.aclose()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.Response.aclose)\ \ * [Asyncio](https://curl-cffi.readthedocs.io/en/stable/api.html#asyncio)\ \ * [WebSocket](https://curl-cffi.readthedocs.io/en/stable/api.html#websocket)\ * [`WebSocket`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket)\ * [`WebSocket.__init__()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.__init__)\ \ * [`WebSocket.connect()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.connect)\ \ * [`WebSocket.recv_fragment()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.recv_fragment)\ \ * [`WebSocket.recv()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.recv)\ \ * [`WebSocket.recv_str()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.recv_str)\ \ * [`WebSocket.recv_json()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.recv_json)\ \ * [`WebSocket.send()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.send)\ \ * [`WebSocket.send_binary()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.send_binary)\ \ * [`WebSocket.send_bytes()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.send_bytes)\ \ * [`WebSocket.send_str()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.send_str)\ \ * [`WebSocket.send_json()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.send_json)\ \ * [`WebSocket.ping()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.ping)\ \ * [`WebSocket.run_forever()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.run_forever)\ \ * [`WebSocket.close()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.WebSocket.close)\ \ * [`AsyncWebSocket`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket)\ * [`AsyncWebSocket.__init__()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.__init__)\ \ * [`AsyncWebSocket.recv()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.recv)\ \ * [`AsyncWebSocket.recv_str()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.recv_str)\ \ * [`AsyncWebSocket.recv_json()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.recv_json)\ \ * [`AsyncWebSocket.send()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.send)\ \ * [`AsyncWebSocket.send_binary()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.send_binary)\ \ * [`AsyncWebSocket.send_bytes()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.send_bytes)\ \ * [`AsyncWebSocket.send_str()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.send_str)\ \ * [`AsyncWebSocket.send_json()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.send_json)\ \ * [`AsyncWebSocket.ping()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.ping)\ \ * [`AsyncWebSocket.close()`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.AsyncWebSocket.close)\ \ * [Exceptions and Warnings](https://curl-cffi.readthedocs.io/en/stable/api.html#exceptions-and-warnings)\ * [Exceptions](https://curl-cffi.readthedocs.io/en/stable/api.html#exceptions)\ * [`RequestException`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.RequestException)\ \ * [`CookieConflict`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.CookieConflict)\ \ * [`SessionClosed`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.SessionClosed)\ \ * [`ImpersonateError`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.ImpersonateError)\ \ * [`InvalidJSONError`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.InvalidJSONError)\ \ * [`HTTPError`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.HTTPError)\ \ * [`IncompleteRead`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.IncompleteRead)\ \ * [`ConnectionError`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.ConnectionError)\ \ * [`DNSError`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.DNSError)\ \ * [`ProxyError`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.ProxyError)\ \ * [`SSLError`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.SSLError)\ \ * [`CertificateVerifyError`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.CertificateVerifyError)\ \ * [`Timeout`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.Timeout)\ \ * [`ConnectTimeout`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.ConnectTimeout)\ \ * [`ReadTimeout`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.ReadTimeout)\ \ * [`URLRequired`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.URLRequired)\ \ * [`TooManyRedirects`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.TooManyRedirects)\ \ * [`MissingSchema`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.MissingSchema)\ \ * [`InvalidSchema`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.InvalidSchema)\ \ * [`InvalidURL`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.InvalidURL)\ \ * [`InvalidHeader`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.InvalidHeader)\ \ * [`InvalidProxyURL`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.InvalidProxyURL)\ \ * [`ChunkedEncodingError`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.ChunkedEncodingError)\ \ * [`ContentDecodingError`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.ContentDecodingError)\ \ * [`StreamConsumedError`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.StreamConsumedError)\ \ * [`RetryError`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.RetryError)\ \ * [`UnrewindableBodyError`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.UnrewindableBodyError)\ \ * [`InterfaceError`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.InterfaceError)\ \ * [Warnings](https://curl-cffi.readthedocs.io/en/stable/api.html#warnings)\ * [`RequestsWarning`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.RequestsWarning)\ \ * [`FileModeWarning`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.FileModeWarning)\ \ * [`RequestsDependencyWarning`](https://curl-cffi.readthedocs.io/en/stable/api.html#curl_cffi.requests.exceptions.RequestsDependencyWarning)\ \ \ #### Previous topic\ \ [Community](https://curl-cffi.readthedocs.io/en/stable/community.html "previous chapter")\ \ #### Next topic\ \ [FAQ](https://curl-cffi.readthedocs.io/en/stable/faq.html "next chapter")\ \ ### This Page\ \ * [Show Source](https://curl-cffi.readthedocs.io/en/stable/_sources/api.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/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) --- # Index — curl_cffi documentation ### Navigation * [index](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html# "General Index") * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Index](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html) Index ===== [**\_**](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html#_) | [**A**](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html#A) | [**C**](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html#C) | [**D**](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html#D) | [**E**](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html#E) | [**F**](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html#F) | [**G**](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html#G) | [**H**](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html#H) | [**I**](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html#I) | [**J**](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html#J) | [**L**](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html#L) | [**M**](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html#M) | [**O**](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html#O) | [**P**](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html#P) | [**R**](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html#R) | [**S**](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html#S) | [**T**](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html#T) | [**U**](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html#U) | [**V**](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html#V) | [**W**](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html#W) \_ -- | | | | --- | --- | | * [\_\_delitem\_\_() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies.__delitem__)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.__delitem__)

* [\_\_getitem\_\_() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies.__getitem__)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.__getitem__)

* [\_\_init\_\_() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.AsyncCurl.__init__)
* [(curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.__init__)

* [(curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlMime.__init__)

* [(curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncSession.__init__)

* [(curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.__init__)

* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Session.__init__)

* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.__init__) | * [\_\_setitem\_\_() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies.__setitem__)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.__setitem__) | A - | | | | --- | --- | | * [aclose() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.aclose)

* [acontent() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.acontent)

* [add\_handle() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.AsyncCurl.add_handle)

* [addpart() (curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlMime.addpart)

* [aiter\_content() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.aiter_content) | * [aiter\_lines() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.aiter_lines)

* [AsyncCurl (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.AsyncCurl)

* [AsyncSession (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncSession)

* [AsyncWebSocket (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket)

* [atext() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.atext)

* [attach() (curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlMime.attach) | C - | | | | --- | --- | | * [CertificateVerifyError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.CertificateVerifyError)

* [charset (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.charset)

* [charset\_encoding (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.charset_encoding)

* [ChunkedEncodingError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.ChunkedEncodingError)

* [clear() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies.clear)

* [close() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.AsyncCurl.close)
* [(curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.close)

* [(curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlMime.close)

* [(curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncSession.close)

* [(curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.close)

* [(curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.close)

* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.close)

* [connect() (curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.connect)

* [ConnectionError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.ConnectionError) | * [ConnectTimeout (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.ConnectTimeout)

* [content (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.content)

* [ContentDecodingError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.ContentDecodingError)

* [CookieConflict (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.CookieConflict)

* [Cookies (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies)

* [cookies (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.cookies)

* [Curl (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl)

* [CurlECode (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode)

* [CurlHttpVersion (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlHttpVersion)

* [CurlInfo (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlInfo)

* [CurlMime (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlMime)

* [CurlMOpt (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlMOpt)

* [CurlOpt (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlOpt)

* [CurlSslVersion (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlSslVersion)

* [CurlWsFlag (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlWsFlag) | D - | | | | --- | --- | | * [debug() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.debug)

* [default\_encoding (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.default_encoding)

* [delete() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies.delete) | * [DNSError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.DNSError)

* [download\_size (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.download_size)

* [duphandle() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.duphandle) | E - | | | | --- | --- | | * [elapsed (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.elapsed) | * [encoding (curl\_cffi.requests.Headers property)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.encoding)
* [(curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.encoding) | F - | | | | --- | --- | | * [FileModeWarning (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.FileModeWarning) | * [from\_list() (curl\_cffi.CurlMime class method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlMime.from_list) | G - | | | | --- | --- | | * [get() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies.get)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.get) | * [get\_list() (curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.get_list)

* [get\_reason\_phrase() (curl\_cffi.Curl static method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.get_reason_phrase)

* [getinfo() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.getinfo) | H - | | | | --- | --- | | * [header\_size (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.header_size)

* [Headers (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers)

* [headers (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.headers) | * [history (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.history)

* [http\_version (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.http_version)

* [HTTPError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.HTTPError) | I - | | | | --- | --- | | * [impersonate() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.impersonate)

* [ImpersonateError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.ImpersonateError)

* [IncompleteRead (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.IncompleteRead)

* [InterfaceError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.InterfaceError)

* [InvalidHeader (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.InvalidHeader) | * [InvalidJSONError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.InvalidJSONError)

* [InvalidProxyURL (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.InvalidProxyURL)

* [InvalidSchema (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.InvalidSchema)

* [InvalidURL (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.InvalidURL)

* [iter\_content() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.iter_content)

* [iter\_lines() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.iter_lines) | J - * [json() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.json) L - | | | | --- | --- | | * [local\_ip (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.local_ip) | * [local\_port (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.local_port) | M - | | | | --- | --- | | * [MissingSchema (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.MissingSchema) | * [multi\_items() (curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.multi_items) | O - * [ok (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.ok) P - | | | | --- | --- | | * [parse\_cookie\_headers() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.parse_cookie_headers)

* [parse\_status\_line() (curl\_cffi.Curl static method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.parse_status_line)

* [perform() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.perform)

* [ping() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.ping)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.ping) | * [primary\_ip (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.primary_ip)

* [primary\_port (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.primary_port)

* [process\_data() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.AsyncCurl.process_data)

* [ProxyError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.ProxyError) | R - | | | | --- | --- | | * [raise\_for\_status() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.raise_for_status)

* [raw() (curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.raw)

* [ReadTimeout (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.ReadTimeout)

* [reason (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.reason)

* [recv() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.recv)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.recv)

* [recv\_fragment() (curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.recv_fragment)

* [recv\_json() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.recv_json)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.recv_json)

* [recv\_str() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.recv_str)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.recv_str)

* [redirect\_count (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.redirect_count)

* [redirect\_url (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.redirect_url) | * [remove\_handle() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.AsyncCurl.remove_handle)

* [Request (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Request)

* [request() (curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncSession.request)
* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Session.request)

* [(in module curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.request)

* [request\_size (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.request_size)

* [RequestException (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.RequestException)

* [RequestsDependencyWarning (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.RequestsDependencyWarning)

* [RequestsWarning (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.RequestsWarning)

* [reset() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.reset)

* [Response (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response)

* [response\_size (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.response_size)

* [RetryError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.RetryError)

* [run\_forever() (curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.run_forever) | S - | | | | --- | --- | | * [send() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.send)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.send)

* [send\_binary() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.send_binary)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.send_binary)

* [send\_bytes() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.send_bytes)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.send_bytes)

* [send\_json() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.send_json)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.send_json)

* [send\_str() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.send_str)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.send_str)

* [Session (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Session) | * [SessionClosed (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.SessionClosed)

* [set() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies.set)

* [set\_exception() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.AsyncCurl.set_exception)

* [set\_result() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.AsyncCurl.set_result)

* [setopt() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.AsyncCurl.setopt)
* [(curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.setopt)

* [socket\_action() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.AsyncCurl.socket_action)

* [SSLError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.SSLError)

* [status\_code (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.status_code)

* [stream() (curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncSession.stream)
* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Session.stream)

* [StreamConsumedError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.StreamConsumedError) | T - | | | | --- | --- | | * [text (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.text) | * [Timeout (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.Timeout)

* [TooManyRedirects (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.TooManyRedirects) | U - | | | | --- | --- | | * [UnrewindableBodyError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.UnrewindableBodyError)

* [update() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies.update)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.update) | * [upload\_size (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.upload_size)

* [url (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.url)

* [URLRequired (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.URLRequired) | V - * [version() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.version) W - | | | | --- | --- | | * [WebSocket (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket)

* [ws\_close() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.ws_close)

* [ws\_connect() (curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncSession.ws_connect)
* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Session.ws_connect) | * [ws\_recv() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.ws_recv)

* [ws\_send() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.ws_send) | ### Quick search ### Navigation * [index](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html# "General Index") * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Index](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html) --- # Supported browser impersonate targets — 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/impersonate/customize.html "How to use my own fingerprints? e.g. okhttp") | * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/fingerprint.html "What is TLS and http/2, http/3 fingerprinting?") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/_index.html) » * [Supported browser impersonate targets](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/targets.html) Supported browser impersonate targets[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/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/v0.14.0/index.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) #### Previous topic [What is TLS and http/2, http/3 fingerprinting?](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/fingerprint.html "previous chapter") #### Next topic [How to use my own fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/customize.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.14.0/_sources/impersonate/targets.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/impersonate/customize.html "How to use my own fingerprints? e.g. okhttp") | * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/fingerprint.html "What is TLS and http/2, http/3 fingerprinting?") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/_index.html) » * [Supported browser impersonate targets](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/targets.html) --- # What is TLS and http/2, http/3 fingerprinting? — 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/impersonate/targets.html "Supported browser impersonate targets") | * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/_index.html "Impersonate Guide") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [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) What is TLS and http/2, http/3 fingerprinting?[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/index.html) * [What is TLS and http/2, http/3 fingerprinting?](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/fingerprint.html#) * [TLS and http/2](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/fingerprint.html#tls-and-http-2) * [http/3](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/fingerprint.html#http-3) #### Previous topic [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/_index.html "previous chapter") #### Next topic [Supported browser impersonate targets](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/targets.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.14.0/_sources/impersonate/fingerprint.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/impersonate/targets.html "Supported browser impersonate targets") | * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/_index.html "Impersonate Guide") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [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) --- # Impersonate Guide — 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/impersonate/fingerprint.html "What is TLS and http/2, http/3 fingerprinting?") | * [previous](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/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/_index.html) Impersonate Guide[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/impersonate/fingerprint.html) * [TLS and http/2](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/fingerprint.html#tls-and-http-2) * [http/3](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/fingerprint.html#http-3) * [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) * [JA3 and Akamai String Format](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/customize.html#ja3-and-akamai-string-format) * [Using CURLOPTs](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/customize.html#using-curlopts) * [How to toggle firefox-specific extensions?](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/customize.html#how-to-toggle-firefox-specific-extensions) * [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/psk.html) * [How do I enable PSK extension anyway?](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/psk.html#how-do-i-enable-psk-extension-anyway) * [Impersonation FAQ](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/faq.html) * [How to check if my impersonation is working?](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/impersonate/faq.html#can-i-change-javascript-fingerprints-with-this-library) * [Why are all the User-Agents macOS?](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/faq.html#why-are-all-the-user-agents-macos) #### Previous topic [Quick Start](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html "previous chapter") #### Next topic [What is TLS and http/2, http/3 fingerprinting?](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/fingerprint.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.14.0/_sources/impersonate/_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/impersonate/fingerprint.html "What is TLS and http/2, http/3 fingerprinting?") | * [previous](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/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/_index.html) --- # Quick Start — 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/impersonate/_index.html "Impersonate Guide") | * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html "curl_cffi’s documentation") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Quick Start](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html) Quick Start[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#quick-start "Link to this heading") ================================================================================================================ Install[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/vs-requests.html) . ### Basic GET requests[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/api.html) . ### Streaming response[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/api.html) #### Response vs Session cookies[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/asyncio.html) . WebSockets[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/websockets.html) . ### [Table of Contents](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) * [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) * [Via pip](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#via-pip) * [Beta versions](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#beta-versions) * [Latest](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#latest) * [requests-like](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#requests-like) * [Basic GET requests](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#basic-get-requests) * [URL params](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#url-params) * [Headers](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#headers) * [Reading Response](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#reading-response) * [POST and uploads](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#post-and-uploads) * [Form submit](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#form-submit) * [Binary data](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#binary-data) * [Posting JSON](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#posting-json) * [Uploads](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#uploads) * [Compressed response](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#compressed-response) * [Response status](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#response-status) * [Response headers](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#response-headers) * [Streaming response](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#streaming-response) * [Redirection and history](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#redirection-and-history) * [Authenticate](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#authenticate) * [Sessions and cookies](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#sessions-and-cookies) * [Response vs Session cookies](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#response-vs-session-cookies) * [Use session without cookies](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html#use-session-without-cookies) * [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) #### Previous topic [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html "previous chapter") #### Next topic [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/_index.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.14.0/_sources/quick_start.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/impersonate/_index.html "Impersonate Guide") | * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html "curl_cffi’s documentation") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Quick Start](https://curl-cffi.readthedocs.io/en/v0.14.0/quick_start.html) --- # Compatibility with requests — 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/cookies.html "Cookies") | * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/advanced.html "Advanced Topics") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.14.0/vs-requests.html) Compatibility with requests[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/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/v0.14.0/index.html) * [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) #### Previous topic [Advanced Topics](https://curl-cffi.readthedocs.io/en/v0.14.0/advanced.html "previous chapter") #### Next topic [Cookies](https://curl-cffi.readthedocs.io/en/v0.14.0/cookies.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.14.0/_sources/vs-requests.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/cookies.html "Cookies") | * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/advanced.html "Advanced Topics") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.14.0/vs-requests.html) --- # TLS PSK(41) Extension — 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/impersonate/faq.html "Impersonation FAQ") | * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/customize.html "How to use my own fingerprints? e.g. okhttp") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/_index.html) » * [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/psk.html) TLS PSK(41) Extension[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/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/v0.14.0/index.html) * [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/psk.html#) * [How do I enable PSK extension anyway?](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/impersonate/customize.html "previous chapter") #### Next topic [Impersonation FAQ](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/faq.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.14.0/_sources/impersonate/psk.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/impersonate/faq.html "Impersonation FAQ") | * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/customize.html "How to use my own fingerprints? e.g. okhttp") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/_index.html) » * [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/psk.html) --- # Impersonation FAQ — 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/advanced.html "Advanced Topics") | * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/psk.html "TLS PSK(41) Extension") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/_index.html) » * [Impersonation FAQ](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/faq.html) Impersonation FAQ[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/faq.html#impersonation-faq "Link to this heading") ================================================================================================================================ How to check if my impersonation is working?[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/index.html) * [Impersonation FAQ](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/faq.html#) * [How to check if my impersonation is working?](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/impersonate/faq.html#can-i-change-javascript-fingerprints-with-this-library) * [Why are all the User-Agents macOS?](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/faq.html#why-are-all-the-user-agents-macos) #### Previous topic [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/psk.html "previous chapter") #### Next topic [Advanced Topics](https://curl-cffi.readthedocs.io/en/v0.14.0/advanced.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.14.0/_sources/impersonate/faq.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/advanced.html "Advanced Topics") | * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/psk.html "TLS PSK(41) Extension") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/_index.html) » * [Impersonation FAQ](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/faq.html) --- # Cookies — 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/community.html "Community") | * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/vs-requests.html "Compatibility with requests") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Cookies](https://curl-cffi.readthedocs.io/en/v0.14.0/cookies.html) Cookies[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/cookies.html#cookies "Link to this heading") ==================================================================================================== Save and load cookies[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/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/v0.14.0/index.html) * [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) #### Previous topic [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.14.0/vs-requests.html "previous chapter") #### Next topic [Community](https://curl-cffi.readthedocs.io/en/v0.14.0/community.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.14.0/_sources/cookies.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/community.html "Community") | * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/vs-requests.html "Compatibility with requests") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Cookies](https://curl-cffi.readthedocs.io/en/v0.14.0/cookies.html) --- # How to use my own fingerprints? e.g. okhttp — 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/impersonate/psk.html "TLS PSK(41) Extension") | * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/targets.html "Supported browser impersonate targets") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/_index.html) » * [How to use my own fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/customize.html) How to use my own fingerprints? e.g. okhttp[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/impersonate/customize.html#id1) . How to toggle firefox-specific extensions?[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/index.html) * [How to use my own fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/customize.html#) * [JA3 and Akamai String Format](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/customize.html#ja3-and-akamai-string-format) * [Using CURLOPTs](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/customize.html#using-curlopts) * [How to toggle firefox-specific extensions?](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/customize.html#how-to-toggle-firefox-specific-extensions) #### Previous topic [Supported browser impersonate targets](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/targets.html "previous chapter") #### Next topic [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/psk.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.14.0/_sources/impersonate/customize.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/impersonate/psk.html "TLS PSK(41) Extension") | * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/targets.html "Supported browser impersonate targets") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/_index.html) » * [How to use my own fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/customize.html) --- # Advanced Topics — 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/vs-requests.html "Compatibility with requests") | * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/faq.html "Impersonation FAQ") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Advanced Topics](https://curl-cffi.readthedocs.io/en/v0.14.0/advanced.html) Advanced Topics[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/advanced.html#advanced-topics "Link to this heading") ===================================================================================================================== Proxies[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/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/v0.14.0/api.html) Using `CURLOPT_*` in requests API[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/index.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) #### Previous topic [Impersonation FAQ](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/faq.html "previous chapter") #### Next topic [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.14.0/vs-requests.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.14.0/_sources/advanced.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/vs-requests.html "Compatibility with requests") | * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/impersonate/faq.html "Impersonation FAQ") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Advanced Topics](https://curl-cffi.readthedocs.io/en/v0.14.0/advanced.html) --- # Community — 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/api.html "API References") | * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/cookies.html "Cookies") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Community](https://curl-cffi.readthedocs.io/en/v0.14.0/community.html) Community[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/community.html#community "Link to this heading") ========================================================================================================== Scrapy integrations[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/index.html) * [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) #### Previous topic [Cookies](https://curl-cffi.readthedocs.io/en/v0.14.0/cookies.html "previous chapter") #### Next topic [API References](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.14.0/_sources/community.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/api.html "API References") | * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/cookies.html "Cookies") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Community](https://curl-cffi.readthedocs.io/en/v0.14.0/community.html) --- # FAQ — 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/changelog.html "Change Log") | * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html "API References") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [FAQ](https://curl-cffi.readthedocs.io/en/v0.14.0/faq.html) FAQ[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/index.html) * [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) #### Previous topic [API References](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html "previous chapter") #### Next topic [Change Log](https://curl-cffi.readthedocs.io/en/v0.14.0/changelog.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.14.0/_sources/faq.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/changelog.html "Change Log") | * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html "API References") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [FAQ](https://curl-cffi.readthedocs.io/en/v0.14.0/faq.html) --- # Change Log — 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/dev.html "Development and contributing") | * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/faq.html "FAQ") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Change Log](https://curl-cffi.readthedocs.io/en/v0.14.0/changelog.html) Change Log[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/faq.html "previous chapter") #### Next topic [Development and contributing](https://curl-cffi.readthedocs.io/en/v0.14.0/dev.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.14.0/_sources/changelog.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/dev.html "Development and contributing") | * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/faq.html "FAQ") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Change Log](https://curl-cffi.readthedocs.io/en/v0.14.0/changelog.html) --- # API References — 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/faq.html "FAQ") | * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/community.html "Community") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [API References](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html) API References[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#api-references "Link to this heading") ============================================================================================================== curl low levl APIs[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl-low-levl-apis "Link to this heading") ---------------------------------------------------------------------------------------------------------------------- ### Curl[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/curl.html#Curl) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/curl.html#Curl.__init__) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/curl.html#Curl.debug) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.debug "Link to this definition") Set debug to True setopt(_option: [CurlOpt](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlOpt "curl_cffi.const.CurlOpt") _, _value: Any_) → int[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/curl.html#Curl.setopt) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/api.html#curl_cffi.CurlInfo "curl_cffi.const.CurlInfo") _) → bytes | int | float | list[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/curl.html#Curl.getinfo) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/curl.html#Curl.version) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/curl.html#Curl.impersonate) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/curl.html#Curl.perform) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") [\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/curl.html#Curl.duphandle) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/curl.html#Curl.reset) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/curl.html#Curl.parse_cookie_headers) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/curl.html#Curl.get_reason_phrase) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/api.html#curl_cffi.CurlHttpVersion "curl_cffi.const.CurlHttpVersion")\ , int, bytes\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/curl.html#Curl.parse_status_line) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/curl.html#Curl.close) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/curl.html#Curl.ws_recv) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/api.html#curl_cffi.CurlWsFlag "curl_cffi.const.CurlWsFlag") \= CurlWsFlag.BINARY_) → int[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/curl.html#Curl.ws_send) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/curl.html#Curl.ws_close) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/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/v0.14.0/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/v0.14.0/api.html#asynccurl "Link to this heading") class curl\_cffi.AsyncCurl(_cacert: str \= ''_, _loop\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/aio.html#AsyncCurl) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/aio.html#AsyncCurl.__init__) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") _)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/aio.html#AsyncCurl.add_handle) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") _)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/aio.html#AsyncCurl.remove_handle) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") _)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/aio.html#AsyncCurl.set_result) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") _, _exception_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/aio.html#AsyncCurl.set_exception) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/aio.html#AsyncCurl.setopt) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/aio.html#AsyncCurl.socket_action) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/aio.html#AsyncCurl.process_data) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/aio.html#AsyncCurl.close) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/api.html#curlmime "Link to this heading") class curl\_cffi.CurlMime(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/curl.html#CurlMime) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlMime "Link to this definition") Wrapper for the `curl_mime_` API. \_\_init\_\_(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/curl.html#CurlMime.__init__) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/curl.html#CurlMime.addpart) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/curl.html#CurlMime.from_list) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/curl.html#CurlMime.attach) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/curl.html#CurlMime.close) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/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/v0.14.0/_modules/curl_cffi/const.html#CurlOpt) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/const.html#CurlInfo) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/const.html#CurlMOpt) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/const.html#CurlECode) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/const.html#CurlHttpVersion) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/const.html#CurlWsFlag) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/const.html#CurlSslVersion) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/api.html#requests-like-api "Link to this heading") -------------------------------------------------------------------------------------------------------------------- ### request method[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/api.html#curl_cffi.requests.Response "curl_cffi.requests.models.Response") [\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests.html#request) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/api.html#sessions "Link to this heading") class curl\_cffi.requests.Session(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/_modules/curl_cffi/requests/session.html#Session) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/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/v0.14.0/_modules/curl_cffi/requests/session.html#Session.__init__) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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 \= , allow\_redirects: bool | None \= None, max\_redirects: int | None \= None, proxies: dict\[str, str\] | None \= None, proxy: str | None \= None, proxy\_auth: tuple\[str, str\] | None \= None, verify: bool | None \= None, referer: str | None \= None, accept\_encoding: str | None \= 'gzip, deflate, br', content\_callback: ~collections.abc.Callable | None \= None, impersonate: ~typing.Literal\['edge99', 'edge101', 'chrome99', 'chrome100', 'chrome101', 'chrome104', 'chrome107', 'chrome110', 'chrome116', 'chrome119', 'chrome120', 'chrome123', 'chrome124', 'chrome131', 'chrome133a', 'chrome136', 'chrome142', 'chrome99\_android', 'chrome131\_android', 'safari153', 'safari155', 'safari170', 'safari172\_ios', 'safari180', 'safari180\_ios', 'safari184', 'safari184\_ios', 'safari260', 'safari2601', 'safari260\_ios', 'firefox133', 'firefox135', 'firefox144', 'tor145', 'chrome', 'edge', 'safari', 'safari\_ios', 'safari\_beta', 'safari\_ios\_beta', 'chrome\_android', 'firefox', 'safari15\_3', 'safari15\_5', 'safari17\_0', 'safari17\_2\_ios', 'safari18\_0', 'safari18\_0\_ios', 'safari18\_4', 'safari18\_4\_ios'\] | None \= None, ja3: str | None \= None, akamai: str | None \= None, extra\_fp: ~curl\_cffi.requests.impersonate.ExtraFingerprints | ~curl\_cffi.requests.impersonate.ExtraFpDict | None \= None, default\_headers: bool | None \= None, default\_encoding: str | ~collections.abc.Callable\[\[bytes\], str\] \= 'utf-8', quote: str | ~typing.Literal\[False\] \= '', http\_version: ~curl\_cffi.const.CurlHttpVersion | ~typing.Literal\['v1', 'v2', 'v2tls', 'v2\_prior\_knowledge', 'v3', 'v3only'\] | None \= None, interface: str | None \= None, cert: str | tuple\[str, str\] | None \= None, stream: bool | None \= None, max\_recv\_speed: int \= 0, multipart: ~curl\_cffi.curl.CurlMime | None \= None, discard\_cookies: bool \= False_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/session.html#Session.request) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Session.request "Link to this definition") Send the request, see `requests.request` for details on parameters. stream(_method: Literal\['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD', 'TRACE', 'PATCH', 'QUERY'\]_, _url: str_, _\*\*kwargs: None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/session.html#Session.stream) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Session.stream "Link to this definition") Equivalent to `with request(..., stream=True) as r:` ws\_connect(_url_, _on\_message\=None_, _on\_error\=None_, _on\_open\=None_, _on\_close\=None_, _\*\*kwargs_) → [WebSocket](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket") [\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/session.html#Session.ws_connect) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Session.ws_connect "Link to this definition") Connects to a websocket url. Note: This method is deprecated, use WebSocket instead. Parameters: * **url** – the ws url to connect. * **on\_message** – message callback, `def on_message(ws, str)` * **on\_error** – error callback, `def on_error(ws, error)` * **on\_open** – open callback, `def on_open(ws)` * **on\_close** – close callback, `def on_close(ws)` Other parameters are the same as `.request` Returns: a WebSocket instance to communicate with the server. class curl\_cffi.requests.AsyncSession(_\*_, _loop\=None_, _async\_curl: [AsyncCurl](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.AsyncCurl "curl_cffi.AsyncCurl") | None \= None_, _max\_clients: int \= 10_, _\*\*kwargs: Unpack\[BaseSessionParams\[R\]\]_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/session.html#AsyncSession) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncSession "Link to this definition") An async request session, cookies and connections will be reused. \_\_init\_\_(_\*_, _loop\=None_, _async\_curl: [AsyncCurl](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.AsyncCurl "curl_cffi.AsyncCurl") | None \= None_, _max\_clients: int \= 10_, _\*\*kwargs: Unpack\[BaseSessionParams\[R\]\]_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/session.html#AsyncSession.__init__) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncSession.__init__ "Link to this definition") Parameters set in the `__init__` method will be override by the same parameter in request method. Parameters: * **loop** – loop to use, if not provided, the running loop will be used. * **async\_curl** – \[AsyncCurl\](/api/curl\_cffi#curl\_cffi.AsyncCurl) object to use. * **max\_clients** – maxmium curl handle to use in the session, this will affect the concurrency ratio. * **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 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. * **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, and it’s recommended to use via `async with`. However, unlike aiohttp, it is not required to use `with`. from curl\_cffi.requests import AsyncSession \# recommended. async with AsyncSession() as s: r \= await s.get("https://example.com") s \= AsyncSession() \# it also works. async 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 \= , allow\_redirects: bool | None \= None, max\_redirects: int | None \= None, proxies: dict\[str, str\] | None \= None, proxy: str | None \= None, proxy\_auth: tuple\[str, str\] | None \= None, verify: bool | None \= None, referer: str | None \= None, accept\_encoding: str | None \= 'gzip, deflate, br', content\_callback: ~collections.abc.Callable | None \= None, impersonate: ~typing.Literal\['edge99', 'edge101', 'chrome99', 'chrome100', 'chrome101', 'chrome104', 'chrome107', 'chrome110', 'chrome116', 'chrome119', 'chrome120', 'chrome123', 'chrome124', 'chrome131', 'chrome133a', 'chrome136', 'chrome142', 'chrome99\_android', 'chrome131\_android', 'safari153', 'safari155', 'safari170', 'safari172\_ios', 'safari180', 'safari180\_ios', 'safari184', 'safari184\_ios', 'safari260', 'safari2601', 'safari260\_ios', 'firefox133', 'firefox135', 'firefox144', 'tor145', 'chrome', 'edge', 'safari', 'safari\_ios', 'safari\_beta', 'safari\_ios\_beta', 'chrome\_android', 'firefox', 'safari15\_3', 'safari15\_5', 'safari17\_0', 'safari17\_2\_ios', 'safari18\_0', 'safari18\_0\_ios', 'safari18\_4', 'safari18\_4\_ios'\] | None \= None, ja3: str | None \= None, akamai: str | None \= None, extra\_fp: ~curl\_cffi.requests.impersonate.ExtraFingerprints | ~curl\_cffi.requests.impersonate.ExtraFpDict | None \= None, default\_headers: bool | None \= None, default\_encoding: str | ~collections.abc.Callable\[\[bytes\], str\] \= 'utf-8', quote: str | ~typing.Literal\[False\] \= '', http\_version: ~curl\_cffi.const.CurlHttpVersion | ~typing.Literal\['v1', 'v2', 'v2tls', 'v2\_prior\_knowledge', 'v3', 'v3only'\] | None \= None, interface: str | None \= None, cert: str | tuple\[str, str\] | None \= None, stream: bool | None \= None, max\_recv\_speed: int \= 0, multipart: ~curl\_cffi.curl.CurlMime | None \= None, discard\_cookies: bool \= False_) → R[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/session.html#AsyncSession.request) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncSession.request "Link to this definition") Send the request, see `curl_cffi.requests.request` for details on args. stream(_method: Literal\['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD', 'TRACE', 'PATCH', 'QUERY'\]_, _url: str_, _\*\*kwargs: None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/session.html#AsyncSession.stream) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncSession.stream "Link to this definition") Equivalent to `async with request(..., stream=True) as r:` async close() → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/session.html#AsyncSession.close) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncSession.close "Link to this definition") Close the session. async ws\_connect(_url: str_, _autoclose: bool \= True_, _params: dict | list | tuple | None \= None_, _headers: 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: CookieJar | dict\[str_, _str\] | list\[tuple\[str_, _str\]\] | None\=None_, _auth: tuple\[str_, _str\] | None\=None_, _timeout: float | tuple\[float_, _float\] | object | None\=_, _allow\_redirects: bool | None \= None_, _max\_redirects: int | None \= None_, _proxies: dict\[str_, _str\] | None\=None_, _proxy: str | None \= None_, _proxy\_auth: tuple\[str_, _str\] | None\=None_, _verify: bool | None \= None_, _referer: str | None \= None_, _accept\_encoding: str | None \= 'gzip_, _deflate_, _br'_, _impersonate: Literal\['edge99'_, _'edge101'_, _'chrome99'_, _'chrome100'_, _'chrome101'_, _'chrome104'_, _'chrome107'_, _'chrome110'_, _'chrome116'_, _'chrome119'_, _'chrome120'_, _'chrome123'_, _'chrome124'_, _'chrome131'_, _'chrome133a'_, _'chrome136'_, _'chrome142'_, _'chrome99\_android'_, _'chrome131\_android'_, _'safari153'_, _'safari155'_, _'safari170'_, _'safari172\_ios'_, _'safari180'_, _'safari180\_ios'_, _'safari184'_, _'safari184\_ios'_, _'safari260'_, _'safari2601'_, _'safari260\_ios'_, _'firefox133'_, _'firefox135'_, _'firefox144'_, _'tor145'_, _'chrome'_, _'edge'_, _'safari'_, _'safari\_ios'_, _'safari\_beta'_, _'safari\_ios\_beta'_, _'chrome\_android'_, _'firefox'_, _'safari15\_3'_, _'safari15\_5'_, _'safari17\_0'_, _'safari17\_2\_ios'_, _'safari18\_0'_, _'safari18\_0\_ios'_, _'safari18\_4'_, _'safari18\_4\_ios'\] | None\=None_, _ja3: str | None \= None_, _akamai: str | None \= None_, _extra\_fp: ExtraFingerprints | ExtraFpDict | None \= None_, _default\_headers: bool | None \= None_, _quote: str | Literal\[False\] \= ''_, _http\_version: Literal\['v1'_, _'v2'_, _'v2tls'_, _'v2\_prior\_knowledge'_, _'v3'_, _'v3only'\] | None\=None_, _interface: str | None \= None_, _cert: str | tuple\[str_, _str\] | None\=None_, _max\_recv\_speed: int \= 0_, _recv\_queue\_size: int \= 512_, _send\_queue\_size: int \= 256_, _max\_send\_batch\_size: int \= 256_, _coalesce\_frames: bool \= False_, _retry\_on\_recv\_error: bool \= False_, _yield\_interval: float \= 0.001_, _fair\_scheduling: bool \= False_, _yield\_mask: int \= 63_) → [AsyncWebSocket](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket "curl_cffi.requests.websockets.AsyncWebSocket") [\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/session.html#AsyncSession.ws_connect) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncSession.ws_connect "Link to this definition") Connects to a WebSocket. Parameters: * **url** – url for the requests. * **autoclose** – whether to close the WebSocket after receiving a close frame. * **params** – query string for the requests. * **headers** – headers to send. * **cookies** – cookies to use. * **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. * **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 str. * **default\_headers** – whether to set default browser headers. * **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. * **interface** – which interface to use. * **cert** – a tuple of (cert, key) filenames for client cert. * **max\_recv\_speed** – maximum receive speed, bytes per second. * **recv\_queue\_size** – The maximum number of incoming WebSocket messages to buffer internally. This queue stores messages received by the Curl socket that are waiting to be consumed by calling recv(). * **send\_queue\_size** – The maximum number of outgoing WebSocket messages to buffer before applying network backpressure. When you call send(…) the message is placed in this queue and transmitted when the Curl socket is next available for sending. * **max\_send\_batch\_size** – The max batch size for sent frames. * **coalesce\_frames** – If True, multiple pending messages in the send queue may be merged into a single WebSocket frame for improved throughput. **Warning:** This breaks the one-to-one mapping of send() calls to frames and should only be used when the application protocol is designed to handle concatenated data streams. Defaults to False. * **retry\_on\_recv\_error** – Retries ws\_recv() if a recv error is raised. Retries up to a limited number of times with a delay in between. * **yield\_interval** – How often to yield control back to the event loop. This is a trade-off between throughput and responsiveness. Lower values means the loop yields more frequently and enables other tasks to run, while higher values are better for throughput. The balanced default is 1ms but you can customize this to fit your application/use case. * **fair\_scheduling** – Changes the I/O priority from favoring receives (5:1) to a balanced ratio (1:1). Enable this to improve send responsiveness under heavy, concurrent load, at the cost of significantly lower overall throughput. * **yield\_mask** – Controls the frequency of cooperative multitasking yields in the read loop. The loop yields every yield\_mask + 1 operations. For efficiency, this value must be a power of two minus one (e.g., 63, 127, 255). Lower values yield more often, improving fairness at the cost of throughput. Higher values yield less often, prioritizing throughput. ### Headers[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#headers "Link to this heading") class curl\_cffi.requests.Headers(_headers: [Headers](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers "curl_cffi.requests.headers.Headers") | Mapping\[str, str | None\] | Mapping\[bytes, bytes | None\] | Sequence\[tuple\[str, str\]\] | Sequence\[tuple\[bytes, bytes\]\] | Sequence\[str | bytes\] | None \= None_, _encoding: str | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/headers.html#Headers) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers "Link to this definition") HTTP headers, as a case-insensitive multi-dict. property encoding: str[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.encoding "Link to this definition") Header encoding is mandated as ascii, but we allow fallbacks to utf-8 or iso-8859-1. raw()[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.raw "Link to this definition") Returns a list of the raw header items, as byte pairs. multi\_items() → list\[tuple\[str, str | None\]\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/headers.html#Headers.multi_items) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.multi_items "Link to this definition") Return a list of (key, value) pairs of headers. Allow multiple occurrences of the same key without concatenating into a single comma separated value. get(_key: str_, _default: Any \= None_) → Any[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/headers.html#Headers.get) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.get "Link to this definition") Return a header value. If multiple occurrences of the header occur then concatenate them together with commas. get\_list(_key: str_, _split\_commas: bool \= False_) → list\[str | None\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/headers.html#Headers.get_list) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.get_list "Link to this definition") Return a list of all header values for a given key. If split\_commas=True is passed, then any comma separated header values are split into multiple return strings. update(\[_E_, \]_\*\*F_) → None.  Update D from mapping/iterable E and F.[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/headers.html#Headers.update) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.update "Link to this definition") If E present and has a .keys() method, does: for k in E: D\[k\] = E\[k\] If E present and lacks .keys() method, does: for (k, v) in E: D\[k\] = v In either case, this is followed by: for k, v in F.items(): D\[k\] = v \_\_getitem\_\_(_key: str_) → str | None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/headers.html#Headers.__getitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.__getitem__ "Link to this definition") Return a single header value. If there are multiple headers with the same key, then we concatenate them with commas. See: [https://tools.ietf.org/html/rfc7230#section-3.2.2](https://tools.ietf.org/html/rfc7230#section-3.2.2) \_\_setitem\_\_(_key: str_, _value: str | None_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/headers.html#Headers.__setitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.__setitem__ "Link to this definition") Set the header key to value, removing any duplicate entries. Retains insertion order. \_\_delitem\_\_(_key: str_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/headers.html#Headers.__delitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.__delitem__ "Link to this definition") Remove the header key. ### Cookies[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#cookies "Link to this heading") class curl\_cffi.requests.Cookies(_cookies: [Cookies](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies "curl_cffi.requests.cookies.Cookies") | CookieJar | dict\[str, str\] | list\[tuple\[str, str\]\] | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/cookies.html#Cookies) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies "Link to this definition") HTTP Cookies, as a mutable mapping. set(_name: str_, _value: str_, _domain: str \= ''_, _path: str \= '/'_, _secure\=False_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/cookies.html#Cookies.set) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies.set "Link to this definition") Set a cookie value by name. May optionally include domain and path. get(_name: str_, _default: str | None \= None_, _domain: str | None \= None_, _path: str | None \= None_) → str | None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/cookies.html#Cookies.get) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies.get "Link to this definition") Get a cookie by name. May optionally include domain and path in order to specify exactly which cookie to retrieve. delete(_name: str_, _domain: str | None \= None_, _path: str | None \= None_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/cookies.html#Cookies.delete) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies.delete "Link to this definition") Delete a cookie by name. May optionally include domain and path in order to specify exactly which cookie to delete. clear(_domain: str | None \= None_, _path: str | None \= None_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/cookies.html#Cookies.clear) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies.clear "Link to this definition") Delete all cookies. Optionally include a domain and path in order to only delete a subset of all the cookies. update(\[_E_, \]_\*\*F_) → None.  Update D from mapping/iterable E and F.[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/cookies.html#Cookies.update) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies.update "Link to this definition") If E present and has a .keys() method, does: for k in E: D\[k\] = E\[k\] If E present and lacks .keys() method, does: for (k, v) in E: D\[k\] = v In either case, this is followed by: for k, v in F.items(): D\[k\] = v \_\_getitem\_\_(_name: str_) → str[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/cookies.html#Cookies.__getitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies.__getitem__ "Link to this definition") \_\_setitem\_\_(_name: str_, _value: str_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/cookies.html#Cookies.__setitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies.__setitem__ "Link to this definition") \_\_delitem\_\_(_name: str_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/cookies.html#Cookies.__delitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies.__delitem__ "Link to this definition") ### Request, Response[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#request-response "Link to this heading") class curl\_cffi.requests.Request(_url: str_, _headers: [Headers](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers "curl_cffi.requests.headers.Headers") _, _method: str_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/models.html#Request) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Request "Link to this definition") Representing a sent request. class curl\_cffi.requests.Response(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_, _request: [Request](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Request "curl_cffi.requests.models.Request") | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/models.html#Response) [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response "Link to this definition") Contains information the server sends. url[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.url "Link to this definition") url used in the request. content[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.content "Link to this definition") response body in bytes. text[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.text "Link to this definition") response body in str. status\_code[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.status_code "Link to this definition") http status code. reason[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.reason "Link to this definition") http response reason, such as OK, Not Found. ok[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.ok "Link to this definition") is status\_code in \[200, 400)?\ \ headers[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.headers "Link to this definition")\ \ response headers.\ \ cookies[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.cookies "Link to this definition")\ \ response cookies.\ \ elapsed[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.elapsed "Link to this definition")\ \ timedelta of the request duration.\ \ encoding[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.encoding "Link to this definition")\ \ http body encoding.\ \ charset[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.charset "Link to this definition")\ \ alias for encoding.\ \ primary\_ip[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.primary_ip "Link to this definition")\ \ primary ip of the server.\ \ primary\_port[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.primary_port "Link to this definition")\ \ primary port of the server.\ \ local\_ip[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.local_ip "Link to this definition")\ \ local ip used in this connection.\ \ local\_port[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.local_port "Link to this definition")\ \ local port used in this connection.\ \ charset\_encoding[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.charset_encoding "Link to this definition")\ \ encoding specified by the Content-Type header.\ \ default\_encoding[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.default_encoding "Link to this definition")\ \ 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.\ \ redirect\_count[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.redirect_count "Link to this definition")\ \ how many redirects happened.\ \ redirect\_url[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.redirect_url "Link to this definition")\ \ the final redirected url.\ \ http\_version[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.http_version "Link to this definition")\ \ http version used.\ \ history[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.history "Link to this definition")\ \ history redirections, only headers are available.\ \ download\_size[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.download_size "Link to this definition")\ \ total downloaded bytes (body).\ \ upload\_size[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.upload_size "Link to this definition")\ \ total uploaded bytes (body).\ \ header\_size[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.header_size "Link to this definition")\ \ total header size.\ \ request\_size[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.request_size "Link to this definition")\ \ request size.\ \ response\_size[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.response_size "Link to this definition")\ \ download\_size + header\_size\ \ raise\_for\_status()[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/models.html#Response.raise_for_status)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.raise_for_status "Link to this definition")\ \ Raise an error if status code is not in \[200, 400)\ \ iter\_lines(_chunk\_size\=None_, _decode\_unicode\=False_, _delimiter\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/models.html#Response.iter_lines)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.iter_lines "Link to this definition")\ \ iterate streaming content line by line, separated by `\n`.\ \ Copied from: [https://requests.readthedocs.io/en/latest/\_modules/requests/models/](https://requests.readthedocs.io/en/latest/_modules/requests/models/)\ which is under the License: Apache 2.0\ \ iter\_content(_chunk\_size\=None_, _decode\_unicode\=False_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/models.html#Response.iter_content)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.iter_content "Link to this definition")\ \ iterate streaming content chunk by chunk in bytes.\ \ json(_\*\*kw_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/models.html#Response.json)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.json "Link to this definition")\ \ return a parsed json object of the content.\ \ close()[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/models.html#Response.close)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.close "Link to this definition")\ \ Close the streaming connection, only valid in stream mode.\ \ async aiter\_lines(_chunk\_size\=None_, _decode\_unicode\=False_, _delimiter\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/models.html#Response.aiter_lines)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.aiter_lines "Link to this definition")\ \ iterate streaming content line by line, separated by `\n`.\ \ Copied from: [https://requests.readthedocs.io/en/latest/\_modules/requests/models/](https://requests.readthedocs.io/en/latest/_modules/requests/models/)\ which is under the License: Apache 2.0\ \ async aiter\_content(_chunk\_size\=None_, _decode\_unicode\=False_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/models.html#Response.aiter_content)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.aiter_content "Link to this definition")\ \ iterate streaming content chunk by chunk in bytes.\ \ async atext() → str[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/models.html#Response.atext)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.atext "Link to this definition")\ \ Return a decoded string.\ \ async acontent() → bytes[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/models.html#Response.acontent)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.acontent "Link to this definition")\ \ wait and read the streaming content in one bytes object.\ \ async aclose()[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/models.html#Response.aclose)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.aclose "Link to this definition")\ \ Close the streaming connection, only valid in stream mode.\ \ Asyncio[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#asyncio "Link to this heading")\ \ ------------------------------------------------------------------------------------------------\ \ WebSocket[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#websocket "Link to this heading")\ \ ----------------------------------------------------------------------------------------------------\ \ class curl\_cffi.requests.WebSocket(_curl: Union\[Curl_, _Any\]\=_, _\*_, _autoclose: bool \= True_, _skip\_utf8\_validation: bool \= False_, _debug: bool \= False_, _on\_open: ON\_OPEN\_T | None \= None_, _on\_close: ON\_CLOSE\_T | None \= None_, _on\_data: ON\_DATA\_T | None \= None_, _on\_message: ON\_MESSAGE\_T | None \= None_, _on\_error: ON\_ERROR\_T | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#WebSocket)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket "Link to this definition")\ \ A WebSocket implementation using libcurl.\ \ \_\_init\_\_(_curl: Union\[Curl_, _Any\]\=_, _\*_, _autoclose: bool \= True_, _skip\_utf8\_validation: bool \= False_, _debug: bool \= False_, _on\_open: ON\_OPEN\_T | None \= None_, _on\_close: ON\_CLOSE\_T | None \= None_, _on\_data: ON\_DATA\_T | None \= None_, _on\_message: ON\_MESSAGE\_T | None \= None_, _on\_error: ON\_ERROR\_T | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#WebSocket.__init__)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.__init__ "Link to this definition")\ \ Parameters:\ \ * **autoclose** – whether to close the WebSocket after receiving a close frame.\ \ * **skip\_utf8\_validation** – whether to skip UTF-8 validation for text frames in run\_forever().\ \ * **debug** – print extra curl debug info.\ \ * **on\_open** – open callback, `def on_open(ws)`\ \ * **on\_close** – close callback, `def on_close(ws, code, reason)`\ \ * **on\_data** – raw data receive callback, `def on_data(ws, data, frame)`\ \ * **on\_message** – message receive callback, `def on_message(ws, message)`\ \ * **on\_error** – error callback, `def on_error(ws, exception)`\ \ \ connect(_url: str, params: Optional\[Union\[dict, list, tuple\]\] \= None, headers: Optional\[HeaderTypes\] \= None, cookies: Optional\[CookieTypes\] \= None, auth: Optional\[tuple\[str, str\]\] \= None, timeout: Optional\[Union\[float, tuple\[float, float\], object\]\] \= , allow\_redirects: bool \= True, max\_redirects: int \= 30, proxies: Optional\[ProxySpec\] \= None, proxy: Optional\[str\] \= None, proxy\_auth: Optional\[tuple\[str, str\]\] \= None, verify: Optional\[bool\] \= None, referer: Optional\[str\] \= None, accept\_encoding: Optional\[str\] \= 'gzip, deflate, br', impersonate: Optional\[BrowserTypeLiteral\] \= None, ja3: Optional\[str\] \= None, akamai: Optional\[str\] \= None, extra\_fp: Optional\[Union\[ExtraFingerprints, ExtraFpDict\]\] \= None, default\_headers: bool \= True, quote: Union\[str, Literal\[False\]\] \= '', http\_version: Optional\[CurlHttpVersion\] \= None, interface: Optional\[str\] \= None, cert: Optional\[Union\[str, tuple\[str, str\]\]\] \= None, max\_recv\_speed: int \= 0, curl\_options: Optional\[dict\[CurlOpt, str\]\] \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#WebSocket.connect)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.connect "Link to this definition")\ \ Connect to the WebSocket.\ \ libcurl automatically handles pings and pongs. ref: [https://curl.se/libcurl/c/libcurl-ws.html](https://curl.se/libcurl/c/libcurl-ws.html)\ \ Parameters:\ \ * **url** – url for the requests.\ \ * **params** – query string for the requests.\ \ * **headers** – headers to send.\ \ * **cookies** – cookies to use.\ \ * **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.\ \ * **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 str.\ \ * **default\_headers** – whether to set default browser headers.\ \ * **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.\ \ * **interface** – which interface to use.\ \ * **cert** – a tuple of (cert, key) filenames for client cert.\ \ * **max\_recv\_speed** – maximum receive speed, bytes per second.\ \ * **curl\_options** – extra curl options to use.\ \ \ recv\_fragment() → tuple\[bytes, CurlWsFrame\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#WebSocket.recv_fragment)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.recv_fragment "Link to this definition")\ \ Receive a single curl websocket fragment as bytes.\ \ recv() → tuple\[bytes, int\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#WebSocket.recv)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.recv "Link to this definition")\ \ Receive a frame as bytes. libcurl splits frames into fragments, so we have to collect all the chunks for a frame.\ \ recv\_str() → str[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#WebSocket.recv_str)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.recv_str "Link to this definition")\ \ Receive a text frame.\ \ recv\_json(_\*, loads: Callable\[\[str\], T\] \= _) → T[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#WebSocket.recv_json)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.recv_json "Link to this definition")\ \ Receive a JSON frame.\ \ Parameters:\ \ **loads** – JSON decoder, default is json.loads.\ \ send(_payload: str | bytes | memoryview_, _flags: [CurlWsFlag](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlWsFlag "curl_cffi.const.CurlWsFlag")\ \= CurlWsFlag.BINARY_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#WebSocket.send)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.send "Link to this definition")\ \ Send a data frame.\ \ Parameters:\ \ * **payload** – data to send.\ \ * **flags** – flags for the frame.\ \ \ send\_binary(_payload: bytes_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#WebSocket.send_binary)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.send_binary "Link to this definition")\ \ Send a binary frame.\ \ Parameters:\ \ **payload** – binary data to send.\ \ send\_bytes(_payload: bytes_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#WebSocket.send_bytes)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.send_bytes "Link to this definition")\ \ Send a binary frame, alias of [`send_binary()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.send_binary "curl_cffi.requests.WebSocket.send_binary")\ .\ \ Parameters:\ \ **payload** – binary data to send.\ \ send\_str(_payload: str_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#WebSocket.send_str)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.send_str "Link to this definition")\ \ Send a text frame.\ \ Parameters:\ \ **payload** – text data to send.\ \ send\_json(_payload: ~typing.Any, \*, dumps: ~collections.abc.Callable\[\[~typing.Any\], str\] \= functools.partial(, separators=(',', ':'))_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#WebSocket.send_json)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.send_json "Link to this definition")\ \ Send a JSON frame.\ \ Parameters:\ \ * **payload** – data to send.\ \ * **dumps** – JSON encoder, default is json.dumps.\ \ \ ping(_payload: str | bytes_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#WebSocket.ping)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.ping "Link to this definition")\ \ Send a ping frame.\ \ Parameters:\ \ **payload** – data to send.\ \ run\_forever(_url: str \= ''_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#WebSocket.run_forever)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.run_forever "Link to this definition")\ \ Run the WebSocket forever. See [`connect()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.connect "curl_cffi.requests.WebSocket.connect")\ for details on parameters.\ \ libcurl automatically handles pings and pongs. ref: [https://curl.se/libcurl/c/libcurl-ws.html](https://curl.se/libcurl/c/libcurl-ws.html)\ \ close(_code: int \= WsCloseCode.OK_, _message: bytes \= b''_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#WebSocket.close)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.close "Link to this definition")\ \ Close the connection.\ \ Parameters:\ \ * **code** – close code.\ \ * **message** – close reason.\ \ \ class curl\_cffi.requests.AsyncWebSocket(_session: [AsyncSession](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncSession "curl_cffi.requests.AsyncSession")\ _, _curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl "curl_cffi.Curl")\ _, _\*_, _autoclose: bool \= True_, _debug: bool \= False_, _recv\_queue\_size: int \= 512_, _send\_queue\_size: int \= 256_, _max\_send\_batch\_size: int \= 256_, _coalesce\_frames: bool \= False_, _retry\_on\_recv\_error: bool \= False_, _yield\_interval: float \= 0.001_, _fair\_scheduling: bool \= False_, _yield\_mask: int \= 63_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket "Link to this definition")\ \ An asyncio WebSocket implementation using libcurl.\ \ NOTE: This object represents a single WebSocket connection. Once closed, it cannot be reopened. A new instance must be created to reconnect.\ \ \_\_init\_\_(_session: [AsyncSession](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncSession "curl_cffi.requests.AsyncSession")\ _, _curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl "curl_cffi.Curl")\ _, _\*_, _autoclose: bool \= True_, _debug: bool \= False_, _recv\_queue\_size: int \= 512_, _send\_queue\_size: int \= 256_, _max\_send\_batch\_size: int \= 256_, _coalesce\_frames: bool \= False_, _retry\_on\_recv\_error: bool \= False_, _yield\_interval: float \= 0.001_, _fair\_scheduling: bool \= False_, _yield\_mask: int \= 63_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.__init__)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.__init__ "Link to this definition")\ \ Initializes an Async WebSocket session.\ \ This class should not be instantiated directly. It is intended to be created via the AsyncSession.ws\_connect() method, which correctly handles setup and initialization of the underlying I/O tasks.\ \ Important\ \ This WebSocket implementation uses a decoupled I/O model. Network operations occur in background tasks. As a result, network-related errors that occur during a send() operation will not be raised by send(). Instead, they are placed into the receive queue and will be raised by the next call to recv().\ \ Parameters:\ \ * **session** ([_AsyncSession_](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncSession "curl_cffi.requests.AsyncSession")\ ) – An instantiated AsyncSession object.\ \ * **curl** ([_Curl_](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl "curl_cffi.Curl")\ ) – The underlying Curl to use.\ \ * **autoclose** (_bool__,_ _optional_) – Close the WS on receiving a close frame.\ \ * **debug** (_bool__,_ _optional_) – Enable debug messages. Defaults to False.\ \ * **recv\_queue\_size** (_int__,_ _optional_) – The maximum number of incoming WebSocket messages to buffer internally. This queue stores messages received by the Curl socket that are waiting to be consumed by calling recv()\ \ * **send\_queue\_size** (_int__,_ _optional_) – The maximum number of outgoing WebSocket messages to buffer before applying network backpressure. When you call send(…) the message is placed in this queue and transmitted when the Curl socket is next available for sending.\ \ * **max\_send\_batch\_size** (_int__,_ _optional_) – The max number of messages per batch.\ \ * **coalesce\_frames** (_bool__,_ _optional_) – Combine multiple frames into a batch.\ \ * **retry\_on\_recv\_error** (_bool__,_ _optional_) – Retry recv on some transient errors.\ \ * **yield\_interval** (_float__,_ _optional_) – How often to yield control in seconds.\ \ * **fair\_scheduling** (_bool__,_ _optional_) – Change the ~5:1 ratio in favor of recv:send to a fairer 1:1 ratio. This decreases recv throughput.\ \ * **yield\_mask** (_int__,_ _optional_) – A bitmask that sets the yield frequency for cooperative multitasking, checked every yield\_mask + 1 operations. Must be a power of two minus one (e.g., 63, 127, 255) for efficient bitwise checks. Lower values increase fairness; higher values increase throughput.\ \ \ async recv(_\*_, _timeout: float | None \= None_) → tuple\[bytes | None, int\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.recv)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.recv "Link to this definition")\ \ Receive a frame as bytes.\ \ This method waits for and returns the next complete data frame from the receive queue.\ \ Parameters:\ \ **timeout** – how many seconds to wait before giving up.\ \ Raises:\ \ * **WebSocketClosed** – If recv() is called on a closed connection after the receive queue is empty.\ \ * **WebSocketTimeout** – If the operation times out.\ \ * **WebSocketError** – A protocol or network error that occurred in a background I/O task, including errors from previous send() operations.\ \ \ Returns:\ \ A tuple with the received payload and flags.\ \ Return type:\ \ tuple\[bytes, int\]\ \ async recv\_str(_\*_, _timeout: float | None \= None_) → str[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.recv_str)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.recv_str "Link to this definition")\ \ Receive a text frame.\ \ Parameters:\ \ **timeout** – how many seconds to wait before giving up.\ \ async recv\_json(_\*, loads: Callable\[\[Union\[str, bytes\]\], T\] \= , timeout: Optional\[float\] \= None_) → T[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.recv_json)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.recv_json "Link to this definition")\ \ Receive a JSON frame.\ \ Parameters:\ \ * **loads** – JSON decoder, default is json.loads.\ \ * **timeout** – how many seconds to wait before giving up.\ \ \ async send(_payload: str | bytes | bytearray | memoryview_, _flags: [CurlWsFlag](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlWsFlag "curl_cffi.const.CurlWsFlag")\ \= CurlWsFlag.BINARY_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.send)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.send "Link to this definition")\ \ Send a data frame.\ \ This method is a lightweight, non-blocking call that places the payload into a send queue. The actual network transmission is handled by a background task.\ \ To guarantee all your messages have been sent await ws.flush(…).\ \ The max frame size supported by libcurl is 65535 bytes. Larger frames will be broken down and sent in chunks of that size.\ \ Parameters:\ \ * **payload** – data to send.\ \ * **flags** – flags for the frame.\ \ \ Raises:\ \ **WebSocketClosed** – The WebSocket is closed.\ \ Note\ \ Due to the asynchronous nature of this client, network errors (e.g., connection dropped) that occur during the actual transmission will NOT be raised by this method. They will be raised by a subsequent call to recv(). Always ensure you are actively receiving data to handle potential connection errors.\ \ Also: If the network is slow and the internal send queue becomes full, this method will block until there is space in the queue.\ \ async send\_binary(_payload: bytes_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.send_binary)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.send_binary "Link to this definition")\ \ Send a binary frame.\ \ Parameters:\ \ **payload** – binary data to send.\ \ For more info, see the docstring for send(…)\ \ async send\_bytes(_payload: bytes_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.send_bytes)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.send_bytes "Link to this definition")\ \ Send a binary frame, alias of [`send_binary()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.send_binary "curl_cffi.requests.AsyncWebSocket.send_binary")\ .\ \ Parameters:\ \ **payload** – binary data to send.\ \ For more info, see the docstring for send(…)\ \ async send\_str(_payload: str_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.send_str)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.send_str "Link to this definition")\ \ Send a text frame.\ \ Parameters:\ \ **payload** – text data to send.\ \ For more info, see the docstring for send(…)\ \ async send\_json(_payload: ~typing.Any, \*, dumps: ~collections.abc.Callable\[\[~typing.Any\], str\] \= functools.partial(, separators=(',', ':'))_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.send_json)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.send_json "Link to this definition")\ \ Send a JSON frame.\ \ Parameters:\ \ * **payload** – data to send.\ \ * **dumps** – JSON encoder, default is json.dumps(…).\ \ \ For more info, see the docstring for send(…)\ \ async ping(_payload: str | bytes_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.ping)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.ping "Link to this definition")\ \ Send a ping frame.\ \ Parameters:\ \ **payload** – data to send.\ \ For more info, see the docstring for send(…)\ \ async close(_code: int \= WsCloseCode.OK_, _message: bytes \= b''_, _timeout: float \= 5.0_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.close)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.close "Link to this definition")\ \ Performs a graceful WebSocket closing handshake and terminates the connection.\ \ This method sends a WebSocket close frame to the peer, waits for queued outgoing messages to be sent, and then shuts down the connection. This is the recommended way to close the session.\ \ Parameters:\ \ * **code** (_int__,_ _optional_) – Close code. Defaults to WsCloseCode.OK.\ \ * **message** (_bytes__,_ _optional_) – Close reason. Defaults to b””.\ \ * **timeout** (_float__,_ _optional_) – How long in seconds to wait closed.\ \ \ Exceptions and Warnings[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#exceptions-and-warnings "Link to this heading")\ \ --------------------------------------------------------------------------------------------------------------------------------\ \ ### Exceptions[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#exceptions "Link to this heading")\ \ We try to follow the requests exception hirearchy, however, some are missing, while some are added.\ \ If an exception is marked as “not used”, please catch the base exception.\ \ class curl\_cffi.requests.exceptions.RequestException(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#RequestException)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.RequestException "Link to this definition")\ \ Base exception for curl\_cffi.requests package\ \ class curl\_cffi.requests.exceptions.CookieConflict(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#CookieConflict)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.CookieConflict "Link to this definition")\ \ Same cookie exists for different domains.\ \ class curl\_cffi.requests.exceptions.SessionClosed(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#SessionClosed)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.SessionClosed "Link to this definition")\ \ The session has already been closed.\ \ class curl\_cffi.requests.exceptions.ImpersonateError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#ImpersonateError)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.ImpersonateError "Link to this definition")\ \ The impersonate config was wrong or impersonate failed.\ \ class curl\_cffi.requests.exceptions.InvalidJSONError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#InvalidJSONError)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.InvalidJSONError "Link to this definition")\ \ A JSON error occurred. not used\ \ class curl\_cffi.requests.exceptions.HTTPError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#HTTPError)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.HTTPError "Link to this definition")\ \ An HTTP error occurred.\ \ class curl\_cffi.requests.exceptions.IncompleteRead(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#IncompleteRead)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.IncompleteRead "Link to this definition")\ \ Incomplete read of content\ \ class curl\_cffi.requests.exceptions.ConnectionError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#ConnectionError)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.ConnectionError "Link to this definition")\ \ A Connection error occurred.\ \ class curl\_cffi.requests.exceptions.DNSError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#DNSError)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.DNSError "Link to this definition")\ \ Could not resolve\ \ class curl\_cffi.requests.exceptions.ProxyError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#ProxyError)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.ProxyError "Link to this definition")\ \ A proxy error occurred.\ \ class curl\_cffi.requests.exceptions.SSLError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#SSLError)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.SSLError "Link to this definition")\ \ An SSL error occurred.\ \ class curl\_cffi.requests.exceptions.CertificateVerifyError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#CertificateVerifyError)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.CertificateVerifyError "Link to this definition")\ \ Raised when certificate validated has failed\ \ class curl\_cffi.requests.exceptions.Timeout(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#Timeout)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.Timeout "Link to this definition")\ \ The request timed out.\ \ class curl\_cffi.requests.exceptions.ConnectTimeout(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#ConnectTimeout)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.ConnectTimeout "Link to this definition")\ \ The request timed out while trying to connect to the remote server.\ \ Requests that produced this error are safe to retry.\ \ not used\ \ class curl\_cffi.requests.exceptions.ReadTimeout(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#ReadTimeout)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.ReadTimeout "Link to this definition")\ \ The server did not send any data in the allotted amount of time. not used\ \ class curl\_cffi.requests.exceptions.URLRequired(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#URLRequired)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.URLRequired "Link to this definition")\ \ A valid URL is required to make a request. not used\ \ class curl\_cffi.requests.exceptions.TooManyRedirects(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#TooManyRedirects)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.TooManyRedirects "Link to this definition")\ \ Too many redirects.\ \ class curl\_cffi.requests.exceptions.MissingSchema(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#MissingSchema)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.MissingSchema "Link to this definition")\ \ The URL scheme (e.g. http or https) is missing. not used\ \ class curl\_cffi.requests.exceptions.InvalidSchema(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#InvalidSchema)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.InvalidSchema "Link to this definition")\ \ The URL scheme provided is either invalid or unsupported. not used\ \ class curl\_cffi.requests.exceptions.InvalidURL(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#InvalidURL)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.InvalidURL "Link to this definition")\ \ The URL provided was somehow invalid.\ \ class curl\_cffi.requests.exceptions.InvalidHeader(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#InvalidHeader)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.InvalidHeader "Link to this definition")\ \ The header value provided was somehow invalid. not used\ \ class curl\_cffi.requests.exceptions.InvalidProxyURL(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#InvalidProxyURL)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.InvalidProxyURL "Link to this definition")\ \ The proxy URL provided is invalid. not used\ \ class curl\_cffi.requests.exceptions.ChunkedEncodingError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#ChunkedEncodingError)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.ChunkedEncodingError "Link to this definition")\ \ The server declared chunked encoding but sent an invalid chunk. not used\ \ class curl\_cffi.requests.exceptions.ContentDecodingError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#ContentDecodingError)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.ContentDecodingError "Link to this definition")\ \ Failed to decode response content. not used\ \ class curl\_cffi.requests.exceptions.StreamConsumedError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#StreamConsumedError)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.StreamConsumedError "Link to this definition")\ \ The content for this response was already consumed. not used\ \ class curl\_cffi.requests.exceptions.RetryError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#RetryError)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.RetryError "Link to this definition")\ \ Custom retries logic failed. not used\ \ class curl\_cffi.requests.exceptions.UnrewindableBodyError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#UnrewindableBodyError)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.UnrewindableBodyError "Link to this definition")\ \ Requests encountered an error when trying to rewind a body. not used\ \ class curl\_cffi.requests.exceptions.InterfaceError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode")\ | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#InterfaceError)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.InterfaceError "Link to this definition")\ \ A specified outgoing interface could not be used.\ \ ### Warnings[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#warnings "Link to this heading")\ \ class curl\_cffi.requests.exceptions.RequestsWarning[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#RequestsWarning)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.RequestsWarning "Link to this definition")\ \ Base warning for Requests. not used\ \ class curl\_cffi.requests.exceptions.FileModeWarning[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#FileModeWarning)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.FileModeWarning "Link to this definition")\ \ A file was opened in text mode, but Requests determined its binary length. not used\ \ class curl\_cffi.requests.exceptions.RequestsDependencyWarning[\[source\]](https://curl-cffi.readthedocs.io/en/v0.14.0/_modules/curl_cffi/requests/exceptions.html#RequestsDependencyWarning)\ [¶](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.RequestsDependencyWarning "Link to this definition")\ \ An imported dependency doesn’t match the expected version range.\ \ ### [Table of Contents](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html)\ \ * [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)\ * [Curl](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl)\ * [`Curl`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl)\ * [`Curl.__init__()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.__init__)\ \ * [`Curl.debug()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.debug)\ \ * [`Curl.setopt()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.setopt)\ \ * [`Curl.getinfo()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.getinfo)\ \ * [`Curl.version()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.version)\ \ * [`Curl.impersonate()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.impersonate)\ \ * [`Curl.perform()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.perform)\ \ * [`Curl.duphandle()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.duphandle)\ \ * [`Curl.reset()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.reset)\ \ * [`Curl.parse_cookie_headers()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.parse_cookie_headers)\ \ * [`Curl.get_reason_phrase()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.get_reason_phrase)\ \ * [`Curl.parse_status_line()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.parse_status_line)\ \ * [`Curl.close()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.close)\ \ * [`Curl.ws_recv()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.ws_recv)\ \ * [`Curl.ws_send()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.ws_send)\ \ * [`Curl.ws_close()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.Curl.ws_close)\ \ * [AsyncCurl](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#asynccurl)\ * [`AsyncCurl`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.AsyncCurl)\ * [`AsyncCurl.__init__()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.AsyncCurl.__init__)\ \ * [`AsyncCurl.add_handle()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.AsyncCurl.add_handle)\ \ * [`AsyncCurl.remove_handle()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.AsyncCurl.remove_handle)\ \ * [`AsyncCurl.set_result()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.AsyncCurl.set_result)\ \ * [`AsyncCurl.set_exception()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.AsyncCurl.set_exception)\ \ * [`AsyncCurl.setopt()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.AsyncCurl.setopt)\ \ * [`AsyncCurl.socket_action()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.AsyncCurl.socket_action)\ \ * [`AsyncCurl.process_data()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.AsyncCurl.process_data)\ \ * [`AsyncCurl.close()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.AsyncCurl.close)\ \ * [CurlMime](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curlmime)\ * [`CurlMime`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlMime)\ * [`CurlMime.__init__()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlMime.__init__)\ \ * [`CurlMime.addpart()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlMime.addpart)\ \ * [`CurlMime.from_list()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlMime.from_list)\ \ * [`CurlMime.attach()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlMime.attach)\ \ * [`CurlMime.close()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlMime.close)\ \ * [Constants](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#constants)\ * [`CurlOpt`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlOpt)\ \ * [`CurlInfo`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlInfo)\ \ * [`CurlMOpt`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlMOpt)\ \ * [`CurlECode`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlECode)\ \ * [`CurlHttpVersion`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlHttpVersion)\ \ * [`CurlWsFlag`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlWsFlag)\ \ * [`CurlSslVersion`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.CurlSslVersion)\ \ * [requests-like API](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#requests-like-api)\ * [request method](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#request-method)\ * [`request()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.request)\ \ * [Sessions](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#sessions)\ * [`Session`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Session)\ * [`Session.__init__()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Session.__init__)\ \ * [`Session.request()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Session.request)\ \ * [`Session.stream()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Session.stream)\ \ * [`Session.ws_connect()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Session.ws_connect)\ \ * [`AsyncSession`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncSession)\ * [`AsyncSession.__init__()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncSession.__init__)\ \ * [`AsyncSession.request()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncSession.request)\ \ * [`AsyncSession.stream()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncSession.stream)\ \ * [`AsyncSession.close()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncSession.close)\ \ * [`AsyncSession.ws_connect()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncSession.ws_connect)\ \ * [Headers](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#headers)\ * [`Headers`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers)\ * [`Headers.encoding`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.encoding)\ \ * [`Headers.raw()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.raw)\ \ * [`Headers.multi_items()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.multi_items)\ \ * [`Headers.get()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.get)\ \ * [`Headers.get_list()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.get_list)\ \ * [`Headers.update()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.update)\ \ * [`Headers.__getitem__()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.__getitem__)\ \ * [`Headers.__setitem__()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.__setitem__)\ \ * [`Headers.__delitem__()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Headers.__delitem__)\ \ * [Cookies](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#cookies)\ * [`Cookies`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies)\ * [`Cookies.set()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies.set)\ \ * [`Cookies.get()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies.get)\ \ * [`Cookies.delete()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies.delete)\ \ * [`Cookies.clear()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies.clear)\ \ * [`Cookies.update()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies.update)\ \ * [`Cookies.__getitem__()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies.__getitem__)\ \ * [`Cookies.__setitem__()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies.__setitem__)\ \ * [`Cookies.__delitem__()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Cookies.__delitem__)\ \ * [Request, Response](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#request-response)\ * [`Request`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Request)\ \ * [`Response`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response)\ * [`Response.url`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.url)\ \ * [`Response.content`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.content)\ \ * [`Response.text`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.text)\ \ * [`Response.status_code`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.status_code)\ \ * [`Response.reason`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.reason)\ \ * [`Response.ok`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.ok)\ \ * [`Response.headers`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.headers)\ \ * [`Response.cookies`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.cookies)\ \ * [`Response.elapsed`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.elapsed)\ \ * [`Response.encoding`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.encoding)\ \ * [`Response.charset`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.charset)\ \ * [`Response.primary_ip`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.primary_ip)\ \ * [`Response.primary_port`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.primary_port)\ \ * [`Response.local_ip`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.local_ip)\ \ * [`Response.local_port`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.local_port)\ \ * [`Response.charset_encoding`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.charset_encoding)\ \ * [`Response.default_encoding`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.default_encoding)\ \ * [`Response.redirect_count`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.redirect_count)\ \ * [`Response.redirect_url`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.redirect_url)\ \ * [`Response.http_version`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.http_version)\ \ * [`Response.history`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.history)\ \ * [`Response.download_size`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.download_size)\ \ * [`Response.upload_size`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.upload_size)\ \ * [`Response.header_size`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.header_size)\ \ * [`Response.request_size`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.request_size)\ \ * [`Response.response_size`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.response_size)\ \ * [`Response.raise_for_status()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.raise_for_status)\ \ * [`Response.iter_lines()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.iter_lines)\ \ * [`Response.iter_content()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.iter_content)\ \ * [`Response.json()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.json)\ \ * [`Response.close()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.close)\ \ * [`Response.aiter_lines()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.aiter_lines)\ \ * [`Response.aiter_content()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.aiter_content)\ \ * [`Response.atext()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.atext)\ \ * [`Response.acontent()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.acontent)\ \ * [`Response.aclose()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.Response.aclose)\ \ * [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)\ * [`WebSocket`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket)\ * [`WebSocket.__init__()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.__init__)\ \ * [`WebSocket.connect()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.connect)\ \ * [`WebSocket.recv_fragment()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.recv_fragment)\ \ * [`WebSocket.recv()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.recv)\ \ * [`WebSocket.recv_str()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.recv_str)\ \ * [`WebSocket.recv_json()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.recv_json)\ \ * [`WebSocket.send()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.send)\ \ * [`WebSocket.send_binary()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.send_binary)\ \ * [`WebSocket.send_bytes()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.send_bytes)\ \ * [`WebSocket.send_str()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.send_str)\ \ * [`WebSocket.send_json()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.send_json)\ \ * [`WebSocket.ping()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.ping)\ \ * [`WebSocket.run_forever()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.run_forever)\ \ * [`WebSocket.close()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.WebSocket.close)\ \ * [`AsyncWebSocket`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket)\ * [`AsyncWebSocket.__init__()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.__init__)\ \ * [`AsyncWebSocket.recv()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.recv)\ \ * [`AsyncWebSocket.recv_str()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.recv_str)\ \ * [`AsyncWebSocket.recv_json()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.recv_json)\ \ * [`AsyncWebSocket.send()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.send)\ \ * [`AsyncWebSocket.send_binary()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.send_binary)\ \ * [`AsyncWebSocket.send_bytes()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.send_bytes)\ \ * [`AsyncWebSocket.send_str()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.send_str)\ \ * [`AsyncWebSocket.send_json()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.send_json)\ \ * [`AsyncWebSocket.ping()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.ping)\ \ * [`AsyncWebSocket.close()`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.AsyncWebSocket.close)\ \ * [Exceptions and Warnings](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#exceptions-and-warnings)\ * [Exceptions](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#exceptions)\ * [`RequestException`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.RequestException)\ \ * [`CookieConflict`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.CookieConflict)\ \ * [`SessionClosed`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.SessionClosed)\ \ * [`ImpersonateError`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.ImpersonateError)\ \ * [`InvalidJSONError`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.InvalidJSONError)\ \ * [`HTTPError`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.HTTPError)\ \ * [`IncompleteRead`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.IncompleteRead)\ \ * [`ConnectionError`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.ConnectionError)\ \ * [`DNSError`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.DNSError)\ \ * [`ProxyError`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.ProxyError)\ \ * [`SSLError`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.SSLError)\ \ * [`CertificateVerifyError`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.CertificateVerifyError)\ \ * [`Timeout`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.Timeout)\ \ * [`ConnectTimeout`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.ConnectTimeout)\ \ * [`ReadTimeout`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.ReadTimeout)\ \ * [`URLRequired`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.URLRequired)\ \ * [`TooManyRedirects`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.TooManyRedirects)\ \ * [`MissingSchema`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.MissingSchema)\ \ * [`InvalidSchema`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.InvalidSchema)\ \ * [`InvalidURL`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.InvalidURL)\ \ * [`InvalidHeader`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.InvalidHeader)\ \ * [`InvalidProxyURL`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.InvalidProxyURL)\ \ * [`ChunkedEncodingError`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.ChunkedEncodingError)\ \ * [`ContentDecodingError`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.ContentDecodingError)\ \ * [`StreamConsumedError`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.StreamConsumedError)\ \ * [`RetryError`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.RetryError)\ \ * [`UnrewindableBodyError`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.UnrewindableBodyError)\ \ * [`InterfaceError`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.InterfaceError)\ \ * [Warnings](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#warnings)\ * [`RequestsWarning`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.RequestsWarning)\ \ * [`FileModeWarning`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.FileModeWarning)\ \ * [`RequestsDependencyWarning`](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html#curl_cffi.requests.exceptions.RequestsDependencyWarning)\ \ \ #### Previous topic\ \ [Community](https://curl-cffi.readthedocs.io/en/v0.14.0/community.html "previous chapter")\ \ #### Next topic\ \ [FAQ](https://curl-cffi.readthedocs.io/en/v0.14.0/faq.html "next chapter")\ \ ### This Page\ \ * [Show Source](https://curl-cffi.readthedocs.io/en/v0.14.0/_sources/api.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/faq.html "FAQ")\ |\ * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/community.html "Community")\ |\ * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html)\ »\ * [API References](https://curl-cffi.readthedocs.io/en/v0.14.0/api.html) --- # Index — curl_cffi documentation ### Navigation * [index](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html# "General Index") * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.13.0/index.html) » * [Index](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html) Index ===== [**\_**](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html#_) | [**A**](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html#A) | [**C**](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html#C) | [**D**](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html#D) | [**E**](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html#E) | [**F**](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html#F) | [**G**](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html#G) | [**H**](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html#H) | [**I**](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html#I) | [**J**](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html#J) | [**L**](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html#L) | [**M**](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html#M) | [**O**](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html#O) | [**P**](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html#P) | [**R**](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html#R) | [**S**](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html#S) | [**T**](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html#T) | [**U**](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html#U) | [**V**](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html#V) | [**W**](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html#W) \_ -- | | | | --- | --- | | * [\_\_delitem\_\_() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Cookies.__delitem__)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Headers.__delitem__)

* [\_\_getitem\_\_() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Cookies.__getitem__)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Headers.__getitem__)

* [\_\_init\_\_() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.AsyncCurl.__init__)
* [(curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.Curl.__init__)

* [(curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.CurlMime.__init__)

* [(curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.AsyncSession.__init__)

* [(curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.AsyncWebSocket.__init__)

* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Session.__init__)

* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.WebSocket.__init__) | * [\_\_setitem\_\_() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Cookies.__setitem__)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Headers.__setitem__) | A - | | | | --- | --- | | * [aclose() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.aclose)

* [acontent() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.acontent)

* [add\_handle() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.AsyncCurl.add_handle)

* [addpart() (curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.CurlMime.addpart)

* [aiter\_content() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.aiter_content) | * [aiter\_lines() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.aiter_lines)

* [AsyncCurl (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.AsyncCurl)

* [AsyncSession (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.AsyncSession)

* [AsyncWebSocket (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.AsyncWebSocket)

* [atext() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.atext)

* [attach() (curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.CurlMime.attach) | C - | | | | --- | --- | | * [CertificateVerifyError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.CertificateVerifyError)

* [charset (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.charset)

* [charset\_encoding (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.charset_encoding)

* [ChunkedEncodingError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.ChunkedEncodingError)

* [clear() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Cookies.clear)

* [close() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.AsyncCurl.close)
* [(curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.Curl.close)

* [(curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.CurlMime.close)

* [(curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.AsyncSession.close)

* [(curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.AsyncWebSocket.close)

* [(curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.close)

* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.WebSocket.close)

* [connect() (curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.WebSocket.connect)

* [ConnectionError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.ConnectionError) | * [ConnectTimeout (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.ConnectTimeout)

* [content (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.content)

* [ContentDecodingError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.ContentDecodingError)

* [CookieConflict (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.CookieConflict)

* [Cookies (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Cookies)

* [cookies (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.cookies)

* [Curl (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.Curl)

* [CurlECode (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.CurlECode)

* [CurlHttpVersion (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.CurlHttpVersion)

* [CurlInfo (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.CurlInfo)

* [CurlMime (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.CurlMime)

* [CurlMOpt (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.CurlMOpt)

* [CurlOpt (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.CurlOpt)

* [CurlSslVersion (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.CurlSslVersion)

* [CurlWsFlag (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.CurlWsFlag) | D - | | | | --- | --- | | * [debug() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.Curl.debug)

* [default\_encoding (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.default_encoding) | * [delete() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Cookies.delete)

* [DNSError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.DNSError)

* [duphandle() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.Curl.duphandle) | E - | | | | --- | --- | | * [elapsed (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.elapsed) | * [encoding (curl\_cffi.requests.Headers property)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Headers.encoding)
* [(curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.encoding) | F - | | | | --- | --- | | * [FileModeWarning (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.FileModeWarning) | * [from\_list() (curl\_cffi.CurlMime class method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.CurlMime.from_list) | G - | | | | --- | --- | | * [get() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Cookies.get)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Headers.get) | * [get\_list() (curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Headers.get_list)

* [get\_reason\_phrase() (curl\_cffi.Curl static method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.Curl.get_reason_phrase)

* [getinfo() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.Curl.getinfo) | H - | | | | --- | --- | | * [Headers (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Headers)

* [headers (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.headers) | * [history (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.history)

* [http\_version (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.http_version)

* [HTTPError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.HTTPError) | I - | | | | --- | --- | | * [impersonate() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.Curl.impersonate)

* [ImpersonateError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.ImpersonateError)

* [IncompleteRead (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.IncompleteRead)

* [InterfaceError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.InterfaceError)

* [InvalidHeader (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.InvalidHeader) | * [InvalidJSONError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.InvalidJSONError)

* [InvalidProxyURL (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.InvalidProxyURL)

* [InvalidSchema (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.InvalidSchema)

* [InvalidURL (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.InvalidURL)

* [iter\_content() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.iter_content)

* [iter\_lines() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.iter_lines) | J - * [json() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.json) L - | | | | --- | --- | | * [local\_ip (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.local_ip) | * [local\_port (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.local_port) | M - | | | | --- | --- | | * [MissingSchema (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.MissingSchema) | * [multi\_items() (curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Headers.multi_items) | O - * [ok (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.ok) P - | | | | --- | --- | | * [parse\_cookie\_headers() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.Curl.parse_cookie_headers)

* [parse\_status\_line() (curl\_cffi.Curl static method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.Curl.parse_status_line)

* [perform() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.Curl.perform)

* [ping() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.AsyncWebSocket.ping)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.WebSocket.ping) | * [primary\_ip (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.primary_ip)

* [primary\_port (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.primary_port)

* [process\_data() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.AsyncCurl.process_data)

* [ProxyError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.ProxyError) | R - | | | | --- | --- | | * [raise\_for\_status() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.raise_for_status)

* [raw() (curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Headers.raw)

* [ReadTimeout (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.ReadTimeout)

* [reason (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.reason)

* [recv() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.AsyncWebSocket.recv)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.WebSocket.recv)

* [recv\_fragment() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.AsyncWebSocket.recv_fragment)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.WebSocket.recv_fragment)

* [recv\_json() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.AsyncWebSocket.recv_json)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.WebSocket.recv_json)

* [recv\_str() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.AsyncWebSocket.recv_str)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.WebSocket.recv_str)

* [redirect\_count (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.redirect_count) | * [redirect\_url (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.redirect_url)

* [remove\_handle() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.AsyncCurl.remove_handle)

* [Request (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Request)

* [request() (curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.AsyncSession.request)
* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Session.request)

* [(in module curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.request)

* [RequestException (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.RequestException)

* [RequestsDependencyWarning (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.RequestsDependencyWarning)

* [RequestsWarning (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.RequestsWarning)

* [reset() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.Curl.reset)

* [Response (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response)

* [RetryError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.RetryError)

* [run\_forever() (curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.WebSocket.run_forever) | S - | | | | --- | --- | | * [send() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.AsyncWebSocket.send)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.WebSocket.send)

* [send\_binary() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.AsyncWebSocket.send_binary)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.WebSocket.send_binary)

* [send\_bytes() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.AsyncWebSocket.send_bytes)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.WebSocket.send_bytes)

* [send\_json() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.AsyncWebSocket.send_json)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.WebSocket.send_json)

* [send\_str() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.AsyncWebSocket.send_str)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.WebSocket.send_str)

* [Session (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Session) | * [SessionClosed (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.SessionClosed)

* [set() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Cookies.set)

* [set\_exception() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.AsyncCurl.set_exception)

* [set\_result() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.AsyncCurl.set_result)

* [setopt() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.AsyncCurl.setopt)
* [(curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.Curl.setopt)

* [socket\_action() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.AsyncCurl.socket_action)

* [SSLError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.SSLError)

* [status\_code (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.status_code)

* [stream() (curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.AsyncSession.stream)
* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Session.stream)

* [StreamConsumedError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.StreamConsumedError) | T - | | | | --- | --- | | * [text (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.text) | * [Timeout (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.Timeout)

* [TooManyRedirects (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.TooManyRedirects) | U - | | | | --- | --- | | * [UnrewindableBodyError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.UnrewindableBodyError)

* [update() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Cookies.update)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Headers.update) | * [url (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Response.url)

* [URLRequired (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.exceptions.URLRequired) | V - * [version() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.Curl.version) W - | | | | --- | --- | | * [WebSocket (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.WebSocket)

* [ws\_close() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.Curl.ws_close)

* [ws\_connect() (curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.AsyncSession.ws_connect)
* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.requests.Session.ws_connect) | * [ws\_recv() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.Curl.ws_recv)

* [ws\_send() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.13.0/api.html#curl_cffi.Curl.ws_send) | ### Quick search ### Navigation * [index](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html# "General Index") * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.13.0/index.html) » * [Index](https://curl-cffi.readthedocs.io/en/v0.13.0/genindex.html) --- # Index — curl_cffi documentation ### Navigation * [index](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html# "General Index") * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.12.0/index.html) » * [Index](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html) Index ===== [**\_**](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html#_) | [**A**](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html#A) | [**C**](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html#C) | [**D**](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html#D) | [**E**](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html#E) | [**F**](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html#F) | [**G**](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html#G) | [**H**](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html#H) | [**I**](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html#I) | [**J**](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html#J) | [**L**](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html#L) | [**M**](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html#M) | [**O**](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html#O) | [**P**](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html#P) | [**R**](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html#R) | [**S**](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html#S) | [**T**](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html#T) | [**U**](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html#U) | [**V**](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html#V) | [**W**](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html#W) \_ -- | | | | --- | --- | | * [\_\_delitem\_\_() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Cookies.__delitem__)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Headers.__delitem__)

* [\_\_getitem\_\_() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Cookies.__getitem__)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Headers.__getitem__)

* [\_\_init\_\_() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.AsyncCurl.__init__)
* [(curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.Curl.__init__)

* [(curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.CurlMime.__init__)

* [(curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.AsyncSession.__init__)

* [(curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.AsyncWebSocket.__init__)

* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Session.__init__)

* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.WebSocket.__init__) | * [\_\_setitem\_\_() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Cookies.__setitem__)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Headers.__setitem__) | A - | | | | --- | --- | | * [aclose() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.aclose)

* [acontent() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.acontent)

* [add\_handle() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.AsyncCurl.add_handle)

* [addpart() (curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.CurlMime.addpart)

* [aiter\_content() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.aiter_content) | * [aiter\_lines() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.aiter_lines)

* [AsyncCurl (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.AsyncCurl)

* [AsyncSession (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.AsyncSession)

* [AsyncWebSocket (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.AsyncWebSocket)

* [atext() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.atext)

* [attach() (curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.CurlMime.attach) | C - | | | | --- | --- | | * [CertificateVerifyError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.CertificateVerifyError)

* [charset (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.charset)

* [charset\_encoding (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.charset_encoding)

* [ChunkedEncodingError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.ChunkedEncodingError)

* [clear() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Cookies.clear)

* [close() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.AsyncCurl.close)
* [(curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.Curl.close)

* [(curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.CurlMime.close)

* [(curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.AsyncSession.close)

* [(curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.AsyncWebSocket.close)

* [(curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.close)

* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.WebSocket.close)

* [connect() (curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.WebSocket.connect)

* [ConnectionError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.ConnectionError) | * [ConnectTimeout (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.ConnectTimeout)

* [content (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.content)

* [ContentDecodingError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.ContentDecodingError)

* [CookieConflict (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.CookieConflict)

* [Cookies (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Cookies)

* [cookies (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.cookies)

* [Curl (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.Curl)

* [CurlECode (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.CurlECode)

* [CurlHttpVersion (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.CurlHttpVersion)

* [CurlInfo (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.CurlInfo)

* [CurlMime (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.CurlMime)

* [CurlMOpt (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.CurlMOpt)

* [CurlOpt (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.CurlOpt)

* [CurlSslVersion (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.CurlSslVersion)

* [CurlWsFlag (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.CurlWsFlag) | D - | | | | --- | --- | | * [debug() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.Curl.debug)

* [default\_encoding (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.default_encoding) | * [delete() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Cookies.delete)

* [DNSError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.DNSError)

* [duphandle() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.Curl.duphandle) | E - | | | | --- | --- | | * [elapsed (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.elapsed) | * [encoding (curl\_cffi.requests.Headers property)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Headers.encoding)
* [(curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.encoding) | F - | | | | --- | --- | | * [FileModeWarning (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.FileModeWarning) | * [from\_list() (curl\_cffi.CurlMime class method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.CurlMime.from_list) | G - | | | | --- | --- | | * [get() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Cookies.get)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Headers.get) | * [get\_list() (curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Headers.get_list)

* [get\_reason\_phrase() (curl\_cffi.Curl static method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.Curl.get_reason_phrase)

* [getinfo() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.Curl.getinfo) | H - | | | | --- | --- | | * [Headers (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Headers)

* [headers (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.headers) | * [history (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.history)

* [http\_version (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.http_version)

* [HTTPError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.HTTPError) | I - | | | | --- | --- | | * [impersonate() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.Curl.impersonate)

* [ImpersonateError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.ImpersonateError)

* [IncompleteRead (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.IncompleteRead)

* [InterfaceError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.InterfaceError)

* [InvalidHeader (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.InvalidHeader) | * [InvalidJSONError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.InvalidJSONError)

* [InvalidProxyURL (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.InvalidProxyURL)

* [InvalidSchema (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.InvalidSchema)

* [InvalidURL (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.InvalidURL)

* [iter\_content() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.iter_content)

* [iter\_lines() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.iter_lines) | J - * [json() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.json) L - | | | | --- | --- | | * [local\_ip (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.local_ip) | * [local\_port (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.local_port) | M - | | | | --- | --- | | * [MissingSchema (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.MissingSchema) | * [multi\_items() (curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Headers.multi_items) | O - * [ok (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.ok) P - | | | | --- | --- | | * [parse\_cookie\_headers() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.Curl.parse_cookie_headers)

* [parse\_status\_line() (curl\_cffi.Curl static method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.Curl.parse_status_line)

* [perform() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.Curl.perform)

* [ping() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.AsyncWebSocket.ping)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.WebSocket.ping) | * [primary\_ip (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.primary_ip)

* [primary\_port (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.primary_port)

* [process\_data() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.AsyncCurl.process_data)

* [ProxyError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.ProxyError) | R - | | | | --- | --- | | * [raise\_for\_status() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.raise_for_status)

* [raw() (curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Headers.raw)

* [ReadTimeout (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.ReadTimeout)

* [reason (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.reason)

* [recv() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.AsyncWebSocket.recv)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.WebSocket.recv)

* [recv\_fragment() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.AsyncWebSocket.recv_fragment)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.WebSocket.recv_fragment)

* [recv\_json() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.AsyncWebSocket.recv_json)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.WebSocket.recv_json)

* [recv\_str() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.AsyncWebSocket.recv_str)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.WebSocket.recv_str)

* [redirect\_count (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.redirect_count) | * [redirect\_url (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.redirect_url)

* [remove\_handle() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.AsyncCurl.remove_handle)

* [Request (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Request)

* [request() (curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.AsyncSession.request)
* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Session.request)

* [(in module curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.request)

* [RequestException (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.RequestException)

* [RequestsDependencyWarning (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.RequestsDependencyWarning)

* [RequestsWarning (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.RequestsWarning)

* [reset() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.Curl.reset)

* [Response (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response)

* [RetryError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.RetryError)

* [run\_forever() (curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.WebSocket.run_forever) | S - | | | | --- | --- | | * [send() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.AsyncWebSocket.send)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.WebSocket.send)

* [send\_binary() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.AsyncWebSocket.send_binary)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.WebSocket.send_binary)

* [send\_bytes() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.AsyncWebSocket.send_bytes)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.WebSocket.send_bytes)

* [send\_json() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.AsyncWebSocket.send_json)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.WebSocket.send_json)

* [send\_str() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.AsyncWebSocket.send_str)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.WebSocket.send_str)

* [Session (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Session) | * [SessionClosed (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.SessionClosed)

* [set() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Cookies.set)

* [set\_exception() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.AsyncCurl.set_exception)

* [set\_result() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.AsyncCurl.set_result)

* [setopt() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.AsyncCurl.setopt)
* [(curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.Curl.setopt)

* [socket\_action() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.AsyncCurl.socket_action)

* [SSLError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.SSLError)

* [status\_code (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.status_code)

* [stream() (curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.AsyncSession.stream)
* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Session.stream)

* [StreamConsumedError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.StreamConsumedError) | T - | | | | --- | --- | | * [text (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.text) | * [Timeout (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.Timeout)

* [TooManyRedirects (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.TooManyRedirects) | U - | | | | --- | --- | | * [UnrewindableBodyError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.UnrewindableBodyError)

* [update() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Cookies.update)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Headers.update) | * [url (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Response.url)

* [URLRequired (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.exceptions.URLRequired) | V - * [version() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.Curl.version) W - | | | | --- | --- | | * [WebSocket (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.WebSocket)

* [ws\_close() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.Curl.ws_close)

* [ws\_connect() (curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.AsyncSession.ws_connect)
* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.requests.Session.ws_connect) | * [ws\_recv() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.Curl.ws_recv)

* [ws\_send() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.12.0/api.html#curl_cffi.Curl.ws_send) | ### Quick search ### Navigation * [index](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html# "General Index") * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.12.0/index.html) » * [Index](https://curl-cffi.readthedocs.io/en/v0.12.0/genindex.html) --- # WebSockets — curl_cffi documentation ### Navigation * [index](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html "General Index") * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [WebSockets](https://curl-cffi.readthedocs.io/en/v0.14.0/websockets.html) WebSockets[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/websockets.html#websockets "Link to this heading") ============================================================================================================= TODO ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.14.0/_sources/websockets.rst.txt) ### Quick search ### Navigation * [index](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html "General Index") * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [WebSockets](https://curl-cffi.readthedocs.io/en/v0.14.0/websockets.html) --- # Index — curl_cffi documentation ### Navigation * [index](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html# "General Index") * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.4/index.html) » * [Index](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html) Index ===== [**\_**](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html#_) | [**A**](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html#A) | [**C**](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html#C) | [**D**](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html#D) | [**E**](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html#E) | [**F**](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html#F) | [**G**](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html#G) | [**H**](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html#H) | [**I**](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html#I) | [**J**](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html#J) | [**L**](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html#L) | [**M**](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html#M) | [**O**](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html#O) | [**P**](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html#P) | [**R**](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html#R) | [**S**](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html#S) | [**T**](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html#T) | [**U**](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html#U) | [**V**](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html#V) | [**W**](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html#W) \_ -- | | | | --- | --- | | * [\_\_delitem\_\_() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Cookies.__delitem__)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Headers.__delitem__)

* [\_\_getitem\_\_() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Cookies.__getitem__)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Headers.__getitem__)

* [\_\_init\_\_() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.AsyncCurl.__init__)
* [(curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.Curl.__init__)

* [(curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.CurlMime.__init__)

* [(curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.AsyncSession.__init__)

* [(curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.AsyncWebSocket.__init__)

* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Session.__init__)

* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.WebSocket.__init__) | * [\_\_setitem\_\_() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Cookies.__setitem__)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Headers.__setitem__) | A - | | | | --- | --- | | * [aclose() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.aclose)

* [acontent() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.acontent)

* [add\_handle() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.AsyncCurl.add_handle)

* [addpart() (curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.CurlMime.addpart)

* [aiter\_content() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.aiter_content) | * [aiter\_lines() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.aiter_lines)

* [AsyncCurl (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.AsyncCurl)

* [AsyncSession (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.AsyncSession)

* [AsyncWebSocket (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.AsyncWebSocket)

* [atext() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.atext)

* [attach() (curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.CurlMime.attach) | C - | | | | --- | --- | | * [CertificateVerifyError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.CertificateVerifyError)

* [charset (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.charset)

* [charset\_encoding (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.charset_encoding)

* [ChunkedEncodingError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.ChunkedEncodingError)

* [clear() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Cookies.clear)

* [close() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.AsyncCurl.close)
* [(curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.Curl.close)

* [(curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.CurlMime.close)

* [(curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.AsyncSession.close)

* [(curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.AsyncWebSocket.close)

* [(curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.close)

* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.WebSocket.close)

* [connect() (curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.WebSocket.connect)

* [ConnectionError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.ConnectionError) | * [ConnectTimeout (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.ConnectTimeout)

* [content (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.content)

* [ContentDecodingError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.ContentDecodingError)

* [CookieConflict (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.CookieConflict)

* [Cookies (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Cookies)

* [cookies (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.cookies)

* [Curl (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.Curl)

* [CurlECode (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.CurlECode)

* [CurlHttpVersion (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.CurlHttpVersion)

* [CurlInfo (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.CurlInfo)

* [CurlMime (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.CurlMime)

* [CurlMOpt (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.CurlMOpt)

* [CurlOpt (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.CurlOpt)

* [CurlSslVersion (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.CurlSslVersion)

* [CurlWsFlag (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.CurlWsFlag) | D - | | | | --- | --- | | * [debug() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.Curl.debug)

* [default\_encoding (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.default_encoding) | * [delete() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Cookies.delete)

* [DNSError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.DNSError)

* [duphandle() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.Curl.duphandle) | E - | | | | --- | --- | | * [elapsed (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.elapsed) | * [encoding (curl\_cffi.requests.Headers property)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Headers.encoding)
* [(curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.encoding) | F - | | | | --- | --- | | * [FileModeWarning (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.FileModeWarning) | * [from\_list() (curl\_cffi.CurlMime class method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.CurlMime.from_list) | G - | | | | --- | --- | | * [get() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Cookies.get)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Headers.get) | * [get\_list() (curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Headers.get_list)

* [get\_reason\_phrase() (curl\_cffi.Curl static method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.Curl.get_reason_phrase)

* [getinfo() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.Curl.getinfo) | H - | | | | --- | --- | | * [Headers (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Headers)

* [headers (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.headers) | * [history (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.history)

* [http\_version (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.http_version)

* [HTTPError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.HTTPError) | I - | | | | --- | --- | | * [impersonate() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.Curl.impersonate)

* [ImpersonateError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.ImpersonateError)

* [IncompleteRead (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.IncompleteRead)

* [InterfaceError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.InterfaceError)

* [InvalidHeader (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.InvalidHeader) | * [InvalidJSONError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.InvalidJSONError)

* [InvalidProxyURL (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.InvalidProxyURL)

* [InvalidSchema (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.InvalidSchema)

* [InvalidURL (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.InvalidURL)

* [iter\_content() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.iter_content)

* [iter\_lines() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.iter_lines) | J - * [json() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.json) L - | | | | --- | --- | | * [local\_ip (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.local_ip) | * [local\_port (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.local_port) | M - | | | | --- | --- | | * [MissingSchema (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.MissingSchema) | * [multi\_items() (curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Headers.multi_items) | O - * [ok (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.ok) P - | | | | --- | --- | | * [parse\_cookie\_headers() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.Curl.parse_cookie_headers)

* [parse\_status\_line() (curl\_cffi.Curl static method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.Curl.parse_status_line)

* [perform() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.Curl.perform)

* [ping() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.AsyncWebSocket.ping)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.WebSocket.ping) | * [primary\_ip (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.primary_ip)

* [primary\_port (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.primary_port)

* [process\_data() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.AsyncCurl.process_data)

* [ProxyError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.ProxyError) | R - | | | | --- | --- | | * [raise\_for\_status() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.raise_for_status)

* [raw() (curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Headers.raw)

* [ReadTimeout (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.ReadTimeout)

* [reason (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.reason)

* [recv() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.AsyncWebSocket.recv)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.WebSocket.recv)

* [recv\_fragment() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.AsyncWebSocket.recv_fragment)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.WebSocket.recv_fragment)

* [recv\_json() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.AsyncWebSocket.recv_json)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.WebSocket.recv_json)

* [recv\_str() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.AsyncWebSocket.recv_str)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.WebSocket.recv_str)

* [redirect\_count (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.redirect_count) | * [redirect\_url (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.redirect_url)

* [remove\_handle() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.AsyncCurl.remove_handle)

* [Request (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Request)

* [request() (curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.AsyncSession.request)
* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Session.request)

* [(in module curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.request)

* [RequestException (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.RequestException)

* [RequestsDependencyWarning (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.RequestsDependencyWarning)

* [RequestsWarning (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.RequestsWarning)

* [reset() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.Curl.reset)

* [Response (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response)

* [RetryError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.RetryError)

* [run\_forever() (curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.WebSocket.run_forever) | S - | | | | --- | --- | | * [send() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.AsyncWebSocket.send)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.WebSocket.send)

* [send\_binary() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.AsyncWebSocket.send_binary)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.WebSocket.send_binary)

* [send\_bytes() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.AsyncWebSocket.send_bytes)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.WebSocket.send_bytes)

* [send\_json() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.AsyncWebSocket.send_json)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.WebSocket.send_json)

* [send\_str() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.AsyncWebSocket.send_str)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.WebSocket.send_str)

* [Session (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Session) | * [SessionClosed (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.SessionClosed)

* [set() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Cookies.set)

* [set\_exception() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.AsyncCurl.set_exception)

* [set\_result() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.AsyncCurl.set_result)

* [setopt() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.AsyncCurl.setopt)
* [(curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.Curl.setopt)

* [socket\_action() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.AsyncCurl.socket_action)

* [SSLError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.SSLError)

* [status\_code (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.status_code)

* [stream() (curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.AsyncSession.stream)
* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Session.stream)

* [StreamConsumedError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.StreamConsumedError) | T - | | | | --- | --- | | * [text (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.text) | * [Timeout (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.Timeout)

* [TooManyRedirects (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.TooManyRedirects) | U - | | | | --- | --- | | * [UnrewindableBodyError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.UnrewindableBodyError)

* [update() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Cookies.update)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Headers.update) | * [url (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Response.url)

* [URLRequired (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.exceptions.URLRequired) | V - * [version() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.Curl.version) W - | | | | --- | --- | | * [WebSocket (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.WebSocket)

* [ws\_close() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.Curl.ws_close)

* [ws\_connect() (curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.AsyncSession.ws_connect)
* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.requests.Session.ws_connect) | * [ws\_recv() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.Curl.ws_recv)

* [ws\_send() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html#curl_cffi.Curl.ws_send) | ### Quick search ### Navigation * [index](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.html# "General Index") * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.4/index.html) » * [Index](https://curl-cffi.readthedocs.io/en/v0.11.4/genindex.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/v0.14.0/genindex.html "General Index") * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Search](https://curl-cffi.readthedocs.io/en/v0.14.0/search.html) Search ====== Searching for multiple words only shows matches that contain all words. ### Navigation * [index](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html "General Index") * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Search](https://curl-cffi.readthedocs.io/en/v0.14.0/search.html) --- # Index — curl_cffi documentation ### Navigation * [index](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html# "General Index") * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.3/index.html) » * [Index](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html) Index ===== [**\_**](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html#_) | [**A**](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html#A) | [**C**](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html#C) | [**D**](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html#D) | [**E**](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html#E) | [**F**](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html#F) | [**G**](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html#G) | [**H**](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html#H) | [**I**](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html#I) | [**J**](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html#J) | [**L**](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html#L) | [**M**](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html#M) | [**O**](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html#O) | [**P**](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html#P) | [**R**](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html#R) | [**S**](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html#S) | [**T**](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html#T) | [**U**](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html#U) | [**V**](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html#V) | [**W**](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html#W) \_ -- | | | | --- | --- | | * [\_\_delitem\_\_() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Cookies.__delitem__)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Headers.__delitem__)

* [\_\_getitem\_\_() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Cookies.__getitem__)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Headers.__getitem__)

* [\_\_init\_\_() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.AsyncCurl.__init__)
* [(curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.Curl.__init__)

* [(curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.CurlMime.__init__)

* [(curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.AsyncSession.__init__)

* [(curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.AsyncWebSocket.__init__)

* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Session.__init__)

* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.WebSocket.__init__) | * [\_\_setitem\_\_() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Cookies.__setitem__)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Headers.__setitem__) | A - | | | | --- | --- | | * [aclose() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.aclose)

* [acontent() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.acontent)

* [add\_handle() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.AsyncCurl.add_handle)

* [addpart() (curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.CurlMime.addpart)

* [aiter\_content() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.aiter_content) | * [aiter\_lines() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.aiter_lines)

* [AsyncCurl (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.AsyncCurl)

* [AsyncSession (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.AsyncSession)

* [AsyncWebSocket (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.AsyncWebSocket)

* [atext() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.atext)

* [attach() (curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.CurlMime.attach) | C - | | | | --- | --- | | * [CertificateVerifyError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.CertificateVerifyError)

* [charset (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.charset)

* [charset\_encoding (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.charset_encoding)

* [ChunkedEncodingError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.ChunkedEncodingError)

* [clear() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Cookies.clear)

* [close() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.AsyncCurl.close)
* [(curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.Curl.close)

* [(curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.CurlMime.close)

* [(curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.AsyncSession.close)

* [(curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.AsyncWebSocket.close)

* [(curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.close)

* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.WebSocket.close)

* [connect() (curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.WebSocket.connect)

* [ConnectionError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.ConnectionError) | * [ConnectTimeout (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.ConnectTimeout)

* [content (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.content)

* [ContentDecodingError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.ContentDecodingError)

* [CookieConflict (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.CookieConflict)

* [Cookies (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Cookies)

* [cookies (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.cookies)

* [Curl (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.Curl)

* [CurlECode (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.CurlECode)

* [CurlHttpVersion (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.CurlHttpVersion)

* [CurlInfo (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.CurlInfo)

* [CurlMime (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.CurlMime)

* [CurlMOpt (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.CurlMOpt)

* [CurlOpt (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.CurlOpt)

* [CurlSslVersion (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.CurlSslVersion)

* [CurlWsFlag (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.CurlWsFlag) | D - | | | | --- | --- | | * [debug() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.Curl.debug)

* [default\_encoding (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.default_encoding) | * [delete() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Cookies.delete)

* [DNSError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.DNSError)

* [duphandle() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.Curl.duphandle) | E - | | | | --- | --- | | * [elapsed (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.elapsed) | * [encoding (curl\_cffi.requests.Headers property)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Headers.encoding)
* [(curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.encoding) | F - | | | | --- | --- | | * [FileModeWarning (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.FileModeWarning) | * [from\_list() (curl\_cffi.CurlMime class method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.CurlMime.from_list) | G - | | | | --- | --- | | * [get() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Cookies.get)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Headers.get) | * [get\_list() (curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Headers.get_list)

* [get\_reason\_phrase() (curl\_cffi.Curl static method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.Curl.get_reason_phrase)

* [getinfo() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.Curl.getinfo) | H - | | | | --- | --- | | * [Headers (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Headers)

* [headers (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.headers) | * [history (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.history)

* [http\_version (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.http_version)

* [HTTPError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.HTTPError) | I - | | | | --- | --- | | * [impersonate() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.Curl.impersonate)

* [ImpersonateError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.ImpersonateError)

* [IncompleteRead (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.IncompleteRead)

* [InterfaceError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.InterfaceError)

* [InvalidHeader (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.InvalidHeader) | * [InvalidJSONError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.InvalidJSONError)

* [InvalidProxyURL (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.InvalidProxyURL)

* [InvalidSchema (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.InvalidSchema)

* [InvalidURL (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.InvalidURL)

* [iter\_content() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.iter_content)

* [iter\_lines() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.iter_lines) | J - * [json() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.json) L - | | | | --- | --- | | * [local\_ip (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.local_ip) | * [local\_port (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.local_port) | M - | | | | --- | --- | | * [MissingSchema (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.MissingSchema) | * [multi\_items() (curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Headers.multi_items) | O - * [ok (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.ok) P - | | | | --- | --- | | * [parse\_cookie\_headers() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.Curl.parse_cookie_headers)

* [parse\_status\_line() (curl\_cffi.Curl static method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.Curl.parse_status_line)

* [perform() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.Curl.perform)

* [ping() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.AsyncWebSocket.ping)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.WebSocket.ping) | * [primary\_ip (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.primary_ip)

* [primary\_port (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.primary_port)

* [process\_data() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.AsyncCurl.process_data)

* [ProxyError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.ProxyError) | R - | | | | --- | --- | | * [raise\_for\_status() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.raise_for_status)

* [raw() (curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Headers.raw)

* [ReadTimeout (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.ReadTimeout)

* [reason (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.reason)

* [recv() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.AsyncWebSocket.recv)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.WebSocket.recv)

* [recv\_fragment() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.AsyncWebSocket.recv_fragment)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.WebSocket.recv_fragment)

* [recv\_json() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.AsyncWebSocket.recv_json)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.WebSocket.recv_json)

* [recv\_str() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.AsyncWebSocket.recv_str)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.WebSocket.recv_str)

* [redirect\_count (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.redirect_count) | * [redirect\_url (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.redirect_url)

* [remove\_handle() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.AsyncCurl.remove_handle)

* [Request (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Request)

* [request() (curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.AsyncSession.request)
* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Session.request)

* [(in module curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.request)

* [RequestException (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.RequestException)

* [RequestsDependencyWarning (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.RequestsDependencyWarning)

* [RequestsWarning (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.RequestsWarning)

* [reset() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.Curl.reset)

* [Response (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response)

* [RetryError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.RetryError)

* [run\_forever() (curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.WebSocket.run_forever) | S - | | | | --- | --- | | * [send() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.AsyncWebSocket.send)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.WebSocket.send)

* [send\_binary() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.AsyncWebSocket.send_binary)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.WebSocket.send_binary)

* [send\_bytes() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.AsyncWebSocket.send_bytes)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.WebSocket.send_bytes)

* [send\_json() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.AsyncWebSocket.send_json)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.WebSocket.send_json)

* [send\_str() (curl\_cffi.requests.AsyncWebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.AsyncWebSocket.send_str)
* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.WebSocket.send_str)

* [Session (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Session) | * [SessionClosed (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.SessionClosed)

* [set() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Cookies.set)

* [set\_exception() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.AsyncCurl.set_exception)

* [set\_result() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.AsyncCurl.set_result)

* [setopt() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.AsyncCurl.setopt)
* [(curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.Curl.setopt)

* [socket\_action() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.AsyncCurl.socket_action)

* [SSLError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.SSLError)

* [status\_code (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.status_code)

* [stream() (curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.AsyncSession.stream)
* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Session.stream)

* [StreamConsumedError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.StreamConsumedError) | T - | | | | --- | --- | | * [text (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.text) | * [Timeout (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.Timeout)

* [TooManyRedirects (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.TooManyRedirects) | U - | | | | --- | --- | | * [UnrewindableBodyError (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.UnrewindableBodyError)

* [update() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Cookies.update)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Headers.update) | * [url (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Response.url)

* [URLRequired (class in curl\_cffi.requests.exceptions)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.exceptions.URLRequired) | V - * [version() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.Curl.version) W - | | | | --- | --- | | * [WebSocket (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.WebSocket)

* [ws\_close() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.Curl.ws_close)

* [ws\_connect() (curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.AsyncSession.ws_connect)
* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.requests.Session.ws_connect) | * [ws\_recv() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.Curl.ws_recv)

* [ws\_send() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html#curl_cffi.Curl.ws_send) | ### Quick search ### Navigation * [index](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html# "General Index") * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.3/index.html) » * [Index](https://curl-cffi.readthedocs.io/en/v0.11.3/genindex.html) --- # Development and contributing — curl_cffi documentation ### Navigation * [index](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html "General Index") * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/changelog.html "Change Log") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Development and contributing](https://curl-cffi.readthedocs.io/en/v0.14.0/dev.html) Development and contributing[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/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/v0.14.0/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/v0.14.0/index.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) #### Previous topic [Change Log](https://curl-cffi.readthedocs.io/en/v0.14.0/changelog.html "previous chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.14.0/_sources/dev.rst.txt) ### Quick search ### Navigation * [index](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html "General Index") * [previous](https://curl-cffi.readthedocs.io/en/v0.14.0/changelog.html "Change Log") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Development and contributing](https://curl-cffi.readthedocs.io/en/v0.14.0/dev.html) --- # Install — curl_cffi documentation Install[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/install.html#install "Link to this heading") =================================================================================================== The fingerprints in 0.6 on Windows are all wrong, you should update to 0.7 if you are on Windows. Only Python 3.8 and above are supported. Python 3.7 has reached its end of life. Via pip[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/install.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/v0.7.1/install.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/v0.7.1/install.html#latest "Link to this heading") ------------------------------------------------------------------------------------------------- To install the latest unstable version from GitHub: git clone https://github.com/yifeikong/curl\_cffi/ cd curl\_cffi make preprocess pip install . [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.1/index.html) ==================================================================== ### Navigation 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) * [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/index.html) * Previous: [Welcome to curl\_cffi’s documentation!](https://curl-cffi.readthedocs.io/en/v0.7.1/index.html "previous chapter") * Next: [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.7.1/impersonate.html "next chapter") ### Quick search --- # Install — curl_cffi documentation Install[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/install.html#install "Link to this heading") ==================================================================================================== The fingerprints in 0.6 on Windows are all wrong, you should update to 0.7 if you are on Windows. Only Python 3.9 and above are supported. Python 3.8 has reached its end of life. Via pip[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/install.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/v0.10.0/install.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/v0.10.0/install.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. [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.10.0/index.html) ===================================================================== ### Navigation 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) * [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/index.html) * Previous: [Welcome to curl\_cffi’s documentation!](https://curl-cffi.readthedocs.io/en/v0.10.0/index.html "previous chapter") * Next: [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.10.0/impersonate.html "next chapter") --- # Install — curl_cffi documentation Install[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/install.html#install "Link to this heading") ==================================================================================================== The fingerprints in 0.6 on Windows are all wrong, you should update to 0.7 if you are on Windows. Only Python 3.9 and above are supported. Python 3.8 has reached its end of life. Via pip[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/install.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/v0.11.2/install.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/v0.11.2/install.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. [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.11.2/index.html) ===================================================================== ### Navigation 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) * [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/index.html) * Previous: [Welcome to curl\_cffi’s documentation!](https://curl-cffi.readthedocs.io/en/v0.11.2/index.html "previous chapter") * Next: [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.11.2/impersonate.html "next chapter") --- # Install — curl_cffi documentation Install[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/install.html#install "Link to this heading") ==================================================================================================== The fingerprints in 0.6 on Windows are all wrong, you should update to 0.7 if you are on Windows. Only Python 3.9 and above are supported. Python 3.8 has reached its end of life. Via pip[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/install.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/v0.11.0/install.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/v0.11.0/install.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. [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.11.0/index.html) ===================================================================== ### Navigation 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) * [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/index.html) * Previous: [Welcome to curl\_cffi’s documentation!](https://curl-cffi.readthedocs.io/en/v0.11.0/index.html "previous chapter") * Next: [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.11.0/impersonate.html "next chapter") --- # Install — curl_cffi documentation Install[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/install.html#install "Link to this heading") ==================================================================================================== The fingerprints in 0.6 on Windows are all wrong, you should update to 0.7 if you are on Windows. Only Python 3.9 and above are supported. Python 3.8 has reached its end of life. Via pip[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/install.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/v0.11.1/install.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/v0.11.1/install.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. [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.11.1/index.html) ===================================================================== ### Navigation 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) * [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/index.html) * Previous: [Welcome to curl\_cffi’s documentation!](https://curl-cffi.readthedocs.io/en/v0.11.1/index.html "previous chapter") * Next: [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.11.1/impersonate.html "next chapter") --- # Install — curl_cffi documentation Install[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/install.html#install "Link to this heading") =================================================================================================== The fingerprints in 0.6 on Windows are all wrong, you should update to 0.7 if you are on Windows. Only Python 3.8 and above are supported. Python 3.7 has reached its end of life. Via pip[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/install.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/v0.7.2/install.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/v0.7.2/install.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 . [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.2/index.html) ==================================================================== ### Navigation 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) * [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/index.html) * Previous: [Welcome to curl\_cffi’s documentation!](https://curl-cffi.readthedocs.io/en/v0.7.2/index.html "previous chapter") * Next: [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.7.2/impersonate.html "next chapter") --- # Install — curl_cffi documentation Install[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/install.html#install "Link to this heading") =================================================================================================== The fingerprints in 0.6 on Windows are all wrong, you should update to 0.7 if you are on Windows. Only Python 3.8 and above are supported. Python 3.7 has reached its end of life. Via pip[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/install.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/v0.7.0/install.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/v0.7.0/install.html#latest "Link to this heading") ------------------------------------------------------------------------------------------------- To install the latest unstable version from GitHub: git clone https://github.com/yifeikong/curl\_cffi/ cd curl\_cffi make preprocess pip install . [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.0/index.html) ==================================================================== ### Navigation 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) * [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/index.html) * Previous: [Welcome to curl\_cffi’s documentation!](https://curl-cffi.readthedocs.io/en/v0.7.0/index.html "previous chapter") * Next: [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.7.0/impersonate.html "next chapter") ### Quick search --- # Quick Start — 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/impersonate/_index.html "Impersonate Guide") | * [previous](https://curl-cffi.readthedocs.io/en/v0.13.0/index.html "curl_cffi’s documentation") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.13.0/index.html) » * [Quick Start](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html) Quick Start[¶](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#quick-start "Link to this heading") ================================================================================================================ Install[¶](https://curl-cffi.readthedocs.io/en/v0.13.0/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/v0.13.0/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/v0.13.0/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/v0.13.0/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/v0.13.0/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/v0.13.0/vs-requests.html) . ### Basic GET requests[¶](https://curl-cffi.readthedocs.io/en/v0.13.0/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/v0.13.0/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/v0.13.0/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/v0.13.0/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/v0.13.0/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/v0.13.0/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/v0.13.0/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/v0.13.0/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/v0.13.0/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/v0.13.0/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/v0.13.0/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/v0.13.0/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/v0.13.0/api.html) . ### Streaming response[¶](https://curl-cffi.readthedocs.io/en/v0.13.0/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/v0.13.0/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/v0.13.0/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/v0.13.0/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/v0.13.0/api.html) #### Response vs Session cookies[¶](https://curl-cffi.readthedocs.io/en/v0.13.0/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/v0.13.0/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/v0.13.0/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/v0.13.0/asyncio.html) . WebSockets[¶](https://curl-cffi.readthedocs.io/en/v0.13.0/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/v0.13.0/websockets.html) . ### [Table of Contents](https://curl-cffi.readthedocs.io/en/v0.13.0/index.html) * [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) * [Via pip](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#via-pip) * [Beta versions](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#beta-versions) * [Latest](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#latest) * [requests-like](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#requests-like) * [Basic GET requests](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#basic-get-requests) * [URL params](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#url-params) * [Headers](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#headers) * [Reading Response](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#reading-response) * [POST and uploads](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#post-and-uploads) * [Form submit](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#form-submit) * [Binary data](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#binary-data) * [Posting JSON](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#posting-json) * [Uploads](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#uploads) * [Compressed response](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#compressed-response) * [Response status](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#response-status) * [Response headers](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#response-headers) * [Streaming response](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#streaming-response) * [Redirection and history](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#redirection-and-history) * [Authenticate](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#authenticate) * [Sessions and cookies](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#sessions-and-cookies) * [Response vs Session cookies](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#response-vs-session-cookies) * [Use session without cookies](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html#use-session-without-cookies) * [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) #### Previous topic [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/v0.13.0/index.html "previous chapter") #### Next topic [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/_index.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.13.0/_sources/quick_start.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/impersonate/_index.html "Impersonate Guide") | * [previous](https://curl-cffi.readthedocs.io/en/v0.13.0/index.html "curl_cffi’s documentation") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.13.0/index.html) » * [Quick Start](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html) --- # Quick Start — 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/impersonate/_index.html "Impersonate Guide") | * [previous](https://curl-cffi.readthedocs.io/en/v0.12.0/index.html "curl_cffi’s documentation") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.12.0/index.html) » * [Quick Start](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html) Quick Start[¶](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#quick-start "Link to this heading") ================================================================================================================ Install[¶](https://curl-cffi.readthedocs.io/en/v0.12.0/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/v0.12.0/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/v0.12.0/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/v0.12.0/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/v0.12.0/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/v0.12.0/vs-requests.html) . ### Basic GET requests[¶](https://curl-cffi.readthedocs.io/en/v0.12.0/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/v0.12.0/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/v0.12.0/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/v0.12.0/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/v0.12.0/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/v0.12.0/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/v0.12.0/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/v0.12.0/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/v0.12.0/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/v0.12.0/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/v0.12.0/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/v0.12.0/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/v0.12.0/api.html) . ### Streaming response[¶](https://curl-cffi.readthedocs.io/en/v0.12.0/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/v0.12.0/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/v0.12.0/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/v0.12.0/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/v0.12.0/api.html) #### Response vs Session cookies[¶](https://curl-cffi.readthedocs.io/en/v0.12.0/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/v0.12.0/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/v0.12.0/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/v0.12.0/asyncio.html) . WebSockets[¶](https://curl-cffi.readthedocs.io/en/v0.12.0/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/v0.12.0/websockets.html) . ### [Table of Contents](https://curl-cffi.readthedocs.io/en/v0.12.0/index.html) * [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) * [Via pip](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#via-pip) * [Beta versions](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#beta-versions) * [Latest](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#latest) * [requests-like](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#requests-like) * [Basic GET requests](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#basic-get-requests) * [URL params](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#url-params) * [Headers](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#headers) * [Reading Response](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#reading-response) * [POST and uploads](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#post-and-uploads) * [Form submit](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#form-submit) * [Binary data](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#binary-data) * [Posting JSON](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#posting-json) * [Uploads](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#uploads) * [Compressed response](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#compressed-response) * [Response status](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#response-status) * [Response headers](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#response-headers) * [Streaming response](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#streaming-response) * [Redirection and history](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#redirection-and-history) * [Authenticate](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#authenticate) * [Sessions and cookies](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#sessions-and-cookies) * [Response vs Session cookies](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#response-vs-session-cookies) * [Use session without cookies](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html#use-session-without-cookies) * [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) #### Previous topic [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/v0.12.0/index.html "previous chapter") #### Next topic [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/_index.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.12.0/_sources/quick_start.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/impersonate/_index.html "Impersonate Guide") | * [previous](https://curl-cffi.readthedocs.io/en/v0.12.0/index.html "curl_cffi’s documentation") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.12.0/index.html) » * [Quick Start](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html) --- # Quick Start — 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/impersonate.html "Impersonate Guide") | * [previous](https://curl-cffi.readthedocs.io/en/v0.11.3/index.html "curl_cffi’s documentation") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.3/index.html) » * [Quick Start](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html) Quick Start[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#quick-start "Link to this heading") ================================================================================================================ Install[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/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/v0.11.3/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/v0.11.3/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/v0.11.3/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/v0.11.3/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/v0.11.3/vs-requests.html) . ### Basic GET requests[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/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/v0.11.3/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/v0.11.3/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/v0.11.3/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/v0.11.3/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/v0.11.3/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/v0.11.3/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/v0.11.3/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/v0.11.3/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/v0.11.3/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/v0.11.3/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/v0.11.3/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/v0.11.3/api.html) . ### Streaming response[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/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/v0.11.3/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/v0.11.3/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/v0.11.3/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/v0.11.3/api.html) #### Response vs Session cookies[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/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/v0.11.3/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/v0.11.3/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/v0.11.3/asyncio.html) . WebSockets[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/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/v0.11.3/websockets.html) . ### [Table of Contents](https://curl-cffi.readthedocs.io/en/v0.11.3/index.html) * [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) * [Via pip](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#via-pip) * [Beta versions](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#beta-versions) * [Latest](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#latest) * [requests-like](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#requests-like) * [Basic GET requests](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#basic-get-requests) * [URL params](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#url-params) * [Headers](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#headers) * [Reading Response](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#reading-response) * [POST and uploads](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#post-and-uploads) * [Form submit](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#form-submit) * [Binary data](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#binary-data) * [Posting JSON](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#posting-json) * [Uploads](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#uploads) * [Compressed response](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#compressed-response) * [Response status](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#response-status) * [Response headers](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#response-headers) * [Streaming response](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#streaming-response) * [Redirection and history](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#redirection-and-history) * [Authenticate](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#authenticate) * [Sessions and cookies](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#sessions-and-cookies) * [Response vs Session cookies](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#response-vs-session-cookies) * [Use session without cookies](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html#use-session-without-cookies) * [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) #### Previous topic [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/v0.11.3/index.html "previous chapter") #### Next topic [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.11.3/_sources/quick_start.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/impersonate.html "Impersonate Guide") | * [previous](https://curl-cffi.readthedocs.io/en/v0.11.3/index.html "curl_cffi’s documentation") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.3/index.html) » * [Quick Start](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html) --- # Impersonate guide — curl_cffi documentation Impersonate guide[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/impersonate.html#impersonate-guide "Link to this heading") ============================================================================================================================ Supported browser versions[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/impersonate.html#supported-browser-versions "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------- `curl_cffi` supports the same browser versions as supported by our [fork](https://github.com/lexiforest/curl-impersonate) of [curl-impersonate](https://github.com/lwthiker/curl-impersonate) : However, only Chrome-like browsers are supported. Firefox support is tracked in [#59](https://github.com/lexiforest/curl_cffi/issues/59) . Browser versions will be added **only** when their fingerprints change. If you see a version, e.g. chrome122, were skipped, you can simply impersonate it with your own headers and the previous version. If you are trying to impersonate a target other than a browser, use `ja3=...` and `akamai=...` 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 * safari15\_3 2 * safari15\_5 2 * safari17\_0 1 * safari17\_2\_ios 1 * safari18\_0 4 * safari18\_0\_ios 4 * safari18\_4 7 * safari18\_4\_ios 7 * 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 Which version to use?[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/impersonate.html#which-version-to-use "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------- Generally speaking, you should use the latest Chrome or Safari versions. As of 0.7, they’re `chrome124`, `safari17_0` and `safari17_2_ios`. To always impersonate the latest avaiable browser versions, you can simply use `chrome`, `safari` and `safari_ios`. import curl\_cffi curl\_cffi.get(url, impersonate\="chrome") iOS has restrictions on WebView and TLS libs, so `safari_x_ios` should work for most 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. 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 "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/v0.11.0/impersonate.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/v0.11.0/impersonate.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/v0.11.0/impersonate.html#id2) . 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 "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/v0.11.0/impersonate.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. [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.11.0/index.html) ===================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Install](https://curl-cffi.readthedocs.io/en/v0.11.0/install.html "previous chapter") * Next: [Cookies](https://curl-cffi.readthedocs.io/en/v0.11.0/cookies.html "next chapter") --- # Impersonate Guide — 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/impersonate/fingerprint.html "What is TLS and http/2, http/3 fingerprinting?") | * [previous](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/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/_index.html) Impersonate Guide[¶](https://curl-cffi.readthedocs.io/en/v0.13.0/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/v0.13.0/impersonate/fingerprint.html) * [TLS and http/2](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/fingerprint.html#tls-and-http-2) * [http/3](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/fingerprint.html#http-3) * [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) * [JA3 and Akamai String Format](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/customize.html#ja3-and-akamai-string-format) * [Using CURLOPTs](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/customize.html#using-curlopts) * [How to toggle firefox-specific extensions?](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/customize.html#how-to-toggle-firefox-specific-extensions) * [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/psk.html) * [How do I enable PSK extension anyway?](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/psk.html#how-do-i-enable-psk-extension-anyway) * [Impersonation FAQ](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/faq.html) * [How to check if my impersonation is working?](https://curl-cffi.readthedocs.io/en/v0.13.0/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/v0.13.0/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/v0.13.0/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/v0.13.0/impersonate/faq.html#can-i-change-javascript-fingerprints-with-this-library) * [Why are all the User-Agents macOS?](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/faq.html#why-are-all-the-user-agents-macos) #### Previous topic [Quick Start](https://curl-cffi.readthedocs.io/en/v0.13.0/quick_start.html "previous chapter") #### Next topic [What is TLS and http/2, http/3 fingerprinting?](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/fingerprint.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.13.0/_sources/impersonate/_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/impersonate/fingerprint.html "What is TLS and http/2, http/3 fingerprinting?") | * [previous](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/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/_index.html) --- # Cookies — curl_cffi documentation Cookies[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/cookies.html#cookies "Link to this heading") ==================================================================================================== How to save and load cookies[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/cookies.html#how-to-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. [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.11.2/index.html) ===================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.11.2/impersonate.html "previous chapter") * Next: [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.11.2/advanced.html "next chapter") --- # Cookies — curl_cffi documentation Cookies[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/cookies.html#cookies "Link to this heading") ==================================================================================================== How to save and load cookies[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/cookies.html#how-to-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. [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.11.0/index.html) ===================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.11.0/impersonate.html "previous chapter") * Next: [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.11.0/advanced.html "next chapter") --- # Impersonate guide — curl_cffi documentation Impersonate guide[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/impersonate.html#impersonate-guide "Link to this heading") =========================================================================================================================== Supported browser versions[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/impersonate.html#supported-browser-versions "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------- `curl_cffi` supports the same browser versions as supported by our [fork](https://github.com/yifeikong/curl-impersonate) of [curl-impersonate](https://github.com/lwthiker/curl-impersonate) : However, only Chrome-like browsers are supported. Firefox support is tracked in [#59](https://github.com/yifeikong/curl_cffi/issues/59) . Browser versions will be added **only** when their fingerprints change. If you see a version, e.g. chrome122, were skipped, you can simply impersonate it with your own headers and the previous version. If you are trying to impersonate a target other than a browser, use `ja3=...` and `akamai=...` 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 * chrome99\_android * edge99 * edge101 * safari15\_3 2 * safari15\_5 2 * safari17\_0 1 * safari17\_2\_ios 1 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. Which version to use?[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/impersonate.html#which-version-to-use "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------- Generally speaking, you should use the latest Chrome or Safari versions. As of 0.7, they’re `chrome124`, `safari17_0` and `safari17_2_ios`. To always impersonate the latest avaiable browser versions, you can simply use `chrome`, `safari` and `safari_ios`. from curl\_cffi import requests requests.get(url, impersonate\="chrome") iOS has restrictions on WebView and TLS libs, so `safari_x_ios` should work for most 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. 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 "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 \= requests.get( url, ja3\=okhttp4\_android10\_ja3, akamai\=okhttp4\_android10\_akamai, extra\_fp\=extra\_fp ) print(r.json()) 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: from curl\_cffi import Curl, CurlOpt, requests c \= Curl() c.setopt(CurlOpt.HTTP2\_PSEUDO\_HEADERS\_ORDER, "masp") \# or requests.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 intial 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/v0.7.1/impersonate.html#id2) . 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 "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/v0.7.1/impersonate.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. [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.1/index.html) ==================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Install](https://curl-cffi.readthedocs.io/en/v0.7.1/install.html "previous chapter") * Next: [Cookies](https://curl-cffi.readthedocs.io/en/v0.7.1/cookies.html "next chapter") ### Quick search --- # Impersonate guide — curl_cffi documentation Impersonate guide[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/impersonate.html#impersonate-guide "Link to this heading") =========================================================================================================================== Supported browser versions[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/impersonate.html#supported-browser-versions "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------- `curl_cffi` supports the same browser versions as supported by our [fork](https://github.com/lexiforest/curl-impersonate) of [curl-impersonate](https://github.com/lwthiker/curl-impersonate) : However, only Chrome-like browsers are supported. Firefox support is tracked in [#59](https://github.com/lexiforest/curl_cffi/issues/59) . Browser versions will be added **only** when their fingerprints change. If you see a version, e.g. chrome122, were skipped, you can simply impersonate it with your own headers and the previous version. If you are trying to impersonate a target other than a browser, use `ja3=...` and `akamai=...` 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 * chrome99\_android * edge99 * edge101 * safari15\_3 2 * safari15\_5 2 * safari17\_0 1 * safari17\_2\_ios 1 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. Which version to use?[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/impersonate.html#which-version-to-use "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------- Generally speaking, you should use the latest Chrome or Safari versions. As of 0.7, they’re `chrome124`, `safari17_0` and `safari17_2_ios`. To always impersonate the latest avaiable browser versions, you can simply use `chrome`, `safari` and `safari_ios`. from curl\_cffi import requests requests.get(url, impersonate\="chrome") iOS has restrictions on WebView and TLS libs, so `safari_x_ios` should work for most 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. 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 "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 \= requests.get( url, ja3\=okhttp4\_android10\_ja3, akamai\=okhttp4\_android10\_akamai, extra\_fp\=extra\_fp ) print(r.json()) 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: from curl\_cffi import Curl, CurlOpt, requests c \= Curl() c.setopt(CurlOpt.HTTP2\_PSEUDO\_HEADERS\_ORDER, "masp") \# or requests.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 intial 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/v0.7.2/impersonate.html#id2) . 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 "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/v0.7.2/impersonate.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. [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.2/index.html) ==================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Install](https://curl-cffi.readthedocs.io/en/v0.7.2/install.html "previous chapter") * Next: [Cookies](https://curl-cffi.readthedocs.io/en/v0.7.2/cookies.html "next chapter") --- # Asyncio — curl_cffi documentation ### Navigation * [index](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html "General Index") * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Asyncio](https://curl-cffi.readthedocs.io/en/v0.14.0/asyncio.html) Asyncio[¶](https://curl-cffi.readthedocs.io/en/v0.14.0/asyncio.html#asyncio "Link to this heading") ==================================================================================================== TODO ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.14.0/_sources/asyncio.rst.txt) ### Quick search ### Navigation * [index](https://curl-cffi.readthedocs.io/en/v0.14.0/genindex.html "General Index") * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.14.0/index.html) » * [Asyncio](https://curl-cffi.readthedocs.io/en/v0.14.0/asyncio.html) --- # Impersonate guide — curl_cffi documentation Impersonate guide[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/impersonate.html#impersonate-guide "Link to this heading") ============================================================================================================================ Supported browser versions[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/impersonate.html#supported-browser-versions "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------- `curl_cffi` supports the same browser versions as supported by our [fork](https://github.com/lexiforest/curl-impersonate) of [curl-impersonate](https://github.com/lwthiker/curl-impersonate) : However, only Chrome-like browsers are supported. Firefox support is tracked in [#59](https://github.com/lexiforest/curl_cffi/issues/59) . Browser versions will be added **only** when their fingerprints change. If you see a version, e.g. chrome122, were skipped, you can simply impersonate it with your own headers and the previous version. If you are trying to impersonate a target other than a browser, use `ja3=...` and `akamai=...` 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 * chrome99\_android * chrome131\_android 4 * edge99 * edge101 * safari15\_3 2 * safari15\_5 2 * safari17\_0 1 * safari17\_2\_ios 1 * safari18\_0 4 * safari18\_0\_ios 4 * firefox133 5 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. Which version to use?[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/impersonate.html#which-version-to-use "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------- Generally speaking, you should use the latest Chrome or Safari versions. As of 0.7, they’re `chrome124`, `safari17_0` and `safari17_2_ios`. To always impersonate the latest avaiable browser versions, you can simply use `chrome`, `safari` and `safari_ios`. import curl\_cffi curl\_cffi.get(url, impersonate\="chrome") iOS has restrictions on WebView and TLS libs, so `safari_x_ios` should work for most 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. 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 "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()) 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 intial 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/v0.10.0/impersonate.html#id2) . 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 "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/v0.10.0/impersonate.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. [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.10.0/index.html) ===================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Install](https://curl-cffi.readthedocs.io/en/v0.10.0/install.html "previous chapter") * Next: [Cookies](https://curl-cffi.readthedocs.io/en/v0.10.0/cookies.html "next chapter") --- # Impersonate guide — curl_cffi documentation Impersonate guide[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/impersonate.html#impersonate-guide "Link to this heading") ============================================================================================================================ Supported browser versions[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/impersonate.html#supported-browser-versions "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------- `curl_cffi` supports the same browser versions as supported by our [fork](https://github.com/lexiforest/curl-impersonate) of [curl-impersonate](https://github.com/lwthiker/curl-impersonate) : However, only Chrome-like browsers are supported. Firefox support is tracked in [#59](https://github.com/lexiforest/curl_cffi/issues/59) . Browser versions will be added **only** when their fingerprints change. If you see a version, e.g. chrome122, were skipped, you can simply impersonate it with your own headers and the previous version. If you are trying to impersonate a target other than a browser, use `ja3=...` and `akamai=...` 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 * safari15\_3 2 * safari15\_5 2 * safari17\_0 1 * safari17\_2\_ios 1 * safari18\_0 4 * safari18\_0\_ios 4 * safari18\_4 7 * safari18\_4\_ios 7 * 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 Which version to use?[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/impersonate.html#which-version-to-use "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------- Generally speaking, you should use the latest Chrome or Safari versions. As of 0.7, they’re `chrome124`, `safari17_0` and `safari17_2_ios`. To always impersonate the latest avaiable browser versions, you can simply use `chrome`, `safari` and `safari_ios`. import curl\_cffi curl\_cffi.get(url, impersonate\="chrome") iOS has restrictions on WebView and TLS libs, so `safari_x_ios` should work for most 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. 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 "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/v0.11.1/impersonate.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/v0.11.1/impersonate.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/v0.11.1/impersonate.html#id2) . 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 "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/v0.11.1/impersonate.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. [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.11.1/index.html) ===================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Install](https://curl-cffi.readthedocs.io/en/v0.11.1/install.html "previous chapter") * Next: [Cookies](https://curl-cffi.readthedocs.io/en/v0.11.1/cookies.html "next chapter") --- # Impersonate guide — curl_cffi documentation Impersonate guide[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/impersonate.html#impersonate-guide "Link to this heading") ============================================================================================================================ Supported browser versions[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/impersonate.html#supported-browser-versions "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------- `curl_cffi` supports the same browser versions as supported by our [fork](https://github.com/lexiforest/curl-impersonate) of [curl-impersonate](https://github.com/lwthiker/curl-impersonate) : However, only Chrome-like browsers are supported. Firefox support is tracked in [#59](https://github.com/lexiforest/curl_cffi/issues/59) . Browser versions will be added **only** when their fingerprints change. If you see a version, e.g. chrome122, were skipped, you can simply impersonate it with your own headers and the previous version. If you are trying to impersonate a target other than a browser, use `ja3=...` and `akamai=...` 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 * 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 Which version to use?[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/impersonate.html#which-version-to-use "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------------- Generally speaking, you should use the latest Chrome or Safari versions. As of 0.7, they’re `chrome124`, `safari17_0` and `safari17_2_ios`. To always impersonate the latest avaiable browser versions, you can simply use `chrome`, `safari` and `safari_ios`. import curl\_cffi curl\_cffi.get(url, impersonate\="chrome") iOS has restrictions on WebView and TLS libs, so `safari_x_ios` should work for most 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. 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 "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()) There are a few special extensions from firefox that you 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) ### JA3 and Akamai String Format[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/impersonate.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/v0.11.2/impersonate.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/v0.11.2/impersonate.html#id2) . 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 "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/v0.11.2/impersonate.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. [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.11.2/index.html) ===================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Install](https://curl-cffi.readthedocs.io/en/v0.11.2/install.html "previous chapter") * Next: [Cookies](https://curl-cffi.readthedocs.io/en/v0.11.2/cookies.html "next chapter") --- # Impersonate guide — curl_cffi documentation Impersonate guide[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/impersonate.html#impersonate-guide "Link to this heading") =========================================================================================================================== Supported browser versions[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/impersonate.html#supported-browser-versions "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------- `curl_cffi` supports the same browser versions as supported by our [fork](https://github.com/yifeikong/curl-impersonate) of [curl-impersonate](https://github.com/lwthiker/curl-impersonate) : However, only Chrome-like browsers are supported. Firefox support is tracked in [#59](https://github.com/yifeikong/curl_cffi/issues/59) . Browser versions will be added **only** when their fingerprints change. If you see a version, e.g. chrome122, were skipped, you can simply impersonate it with your own headers and the previous version. If you are trying to impersonate a target other than a browser, use `ja3=...` and `akamai=...` 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 * chrome99\_android * edge99 * edge101 * safari15\_3 2 * safari15\_5 2 * safari17\_0 1 * safari17\_2\_ios 1 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. Which version to use?[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/impersonate.html#which-version-to-use "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------------- Generally speaking, you should use the latest Chrome or Safari versions. As of 0.7, they’re `chrome124`, `safari17_0` and `safari17_2_ios`. To always impersonate the latest avaiable browser versions, you can simply use `chrome`, `safari` and `safari_ios`. from curl\_cffi import requests requests.get(url, impersonate\="chrome") iOS has restrictions on WebView and TLS libs, so `safari_x_ios` should work for most 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. 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 "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 \= requests.get( url, ja3\=okhttp4\_android10\_ja3, akamai\=okhttp4\_android10\_akamai, extra\_fp\=extra\_fp ) print(r.json()) 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: from curl\_cffi import Curl, CurlOpt, requests c \= Curl() c.setopt(CurlOpt.HTTP2\_PSEUDO\_HEADERS\_ORDER, "masp") \# or requests.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 intial 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/v0.7.0/impersonate.html#id2) . 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 "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/v0.7.0/impersonate.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. [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.0/index.html) ==================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Install](https://curl-cffi.readthedocs.io/en/v0.7.0/install.html "previous chapter") * Next: [Cookies](https://curl-cffi.readthedocs.io/en/v0.7.0/cookies.html "next chapter") ### Quick search --- # What is TLS and http/2, http/3 fingerprinting? — 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/impersonate/targets.html "Supported browser impersonate targets") | * [previous](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/_index.html "Impersonate Guide") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.13.0/index.html) » * [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) What is TLS and http/2, http/3 fingerprinting?[¶](https://curl-cffi.readthedocs.io/en/v0.13.0/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/v0.13.0/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/v0.13.0/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/v0.13.0/index.html) * [What is TLS and http/2, http/3 fingerprinting?](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/fingerprint.html#) * [TLS and http/2](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/fingerprint.html#tls-and-http-2) * [http/3](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/fingerprint.html#http-3) #### Previous topic [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/_index.html "previous chapter") #### Next topic [Supported browser impersonate targets](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/targets.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.13.0/_sources/impersonate/fingerprint.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/impersonate/targets.html "Supported browser impersonate targets") | * [previous](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/_index.html "Impersonate Guide") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.13.0/index.html) » * [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) --- # Quick Start — 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/impersonate.html "Impersonate Guide") | * [previous](https://curl-cffi.readthedocs.io/en/v0.11.4/index.html "curl_cffi’s documentation") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.4/index.html) » * [Quick Start](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html) Quick Start[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#quick-start "Link to this heading") ================================================================================================================ Install[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/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/v0.11.4/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/v0.11.4/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/v0.11.4/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/v0.11.4/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/v0.11.4/vs-requests.html) . ### Basic GET requests[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/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/v0.11.4/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/v0.11.4/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/v0.11.4/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/v0.11.4/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/v0.11.4/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/v0.11.4/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/v0.11.4/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/v0.11.4/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/v0.11.4/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/v0.11.4/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/v0.11.4/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/v0.11.4/api.html) . ### Streaming response[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/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/v0.11.4/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/v0.11.4/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/v0.11.4/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/v0.11.4/api.html) #### Response vs Session cookies[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/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/v0.11.4/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/v0.11.4/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/v0.11.4/asyncio.html) . WebSockets[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/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/v0.11.4/websockets.html) . ### [Table of Contents](https://curl-cffi.readthedocs.io/en/v0.11.4/index.html) * [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) * [Via pip](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#via-pip) * [Beta versions](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#beta-versions) * [Latest](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#latest) * [requests-like](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#requests-like) * [Basic GET requests](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#basic-get-requests) * [URL params](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#url-params) * [Headers](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#headers) * [Reading Response](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#reading-response) * [POST and uploads](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#post-and-uploads) * [Form submit](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#form-submit) * [Binary data](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#binary-data) * [Posting JSON](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#posting-json) * [Uploads](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#uploads) * [Compressed response](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#compressed-response) * [Response status](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#response-status) * [Response headers](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#response-headers) * [Streaming response](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#streaming-response) * [Redirection and history](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#redirection-and-history) * [Authenticate](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#authenticate) * [Sessions and cookies](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#sessions-and-cookies) * [Response vs Session cookies](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#response-vs-session-cookies) * [Use session without cookies](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html#use-session-without-cookies) * [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) #### Previous topic [curl\_cffi’s documentation](https://curl-cffi.readthedocs.io/en/v0.11.4/index.html "previous chapter") #### Next topic [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.11.4/_sources/quick_start.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/impersonate.html "Impersonate Guide") | * [previous](https://curl-cffi.readthedocs.io/en/v0.11.4/index.html "curl_cffi’s documentation") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.4/index.html) » * [Quick Start](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html) --- # What is TLS and http/2, http/3 fingerprinting? — 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/impersonate/targets.html "Supported browser impersonate targets") | * [previous](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/_index.html "Impersonate Guide") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.12.0/index.html) » * [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) What is TLS and http/2, http/3 fingerprinting?[¶](https://curl-cffi.readthedocs.io/en/v0.12.0/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/v0.12.0/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/v0.12.0/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/v0.12.0/index.html) * [What is TLS and http/2, http/3 fingerprinting?](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/fingerprint.html#) * [TLS and http/2](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/fingerprint.html#tls-and-http-2) * [http/3](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/fingerprint.html#http-3) #### Previous topic [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/_index.html "previous chapter") #### Next topic [Supported browser impersonate targets](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/targets.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.12.0/_sources/impersonate/fingerprint.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/impersonate/targets.html "Supported browser impersonate targets") | * [previous](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/_index.html "Impersonate Guide") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.12.0/index.html) » * [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) --- # Cookies — curl_cffi documentation Cookies[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/cookies.html#cookies "Link to this heading") ==================================================================================================== How to save and load cookies[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/cookies.html#how-to-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. [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.10.0/index.html) ===================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.10.0/impersonate.html "previous chapter") * Next: [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.10.0/advanced.html "next chapter") --- # Cookies — curl_cffi documentation Cookies[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/cookies.html#cookies "Link to this heading") =================================================================================================== How to save and load cookies[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/cookies.html#how-to-save-and-load-cookies "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------------------- import pickle \# import httpx from curl\_cffi import requests def save\_cookies(client): with open("cookies.pk", "wb") as f: pickle.dump(client.cookies.jar, 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 \= requests.Session(cookies\=load\_cookies()) save\_cookies(client) [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.0/index.html) ==================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.7.0/impersonate.html "previous chapter") * Next: [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.7.0/advanced.html "next chapter") ### Quick search --- # Impersonate Guide — 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/impersonate/fingerprint.html "What is TLS and http/2, http/3 fingerprinting?") | * [previous](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/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/_index.html) Impersonate Guide[¶](https://curl-cffi.readthedocs.io/en/v0.12.0/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/v0.12.0/impersonate/fingerprint.html) * [TLS and http/2](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/fingerprint.html#tls-and-http-2) * [http/3](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/fingerprint.html#http-3) * [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) * [JA3 and Akamai String Format](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/customize.html#ja3-and-akamai-string-format) * [Using CURLOPTs](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/customize.html#using-curlopts) * [How to toggle firefox-specific extensions?](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/customize.html#how-to-toggle-firefox-specific-extensions) * [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/psk.html) * [How do I enable PSK extension anyway?](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/psk.html#how-do-i-enable-psk-extension-anyway) * [Impersonation FAQ](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/faq.html) * [How to check if my impersonation is working?](https://curl-cffi.readthedocs.io/en/v0.12.0/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/v0.12.0/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/v0.12.0/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/v0.12.0/impersonate/faq.html#can-i-change-javascript-fingerprints-with-this-library) * [Why are all the User-Agents macOS?](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/faq.html#why-are-all-the-user-agents-macos) #### Previous topic [Quick Start](https://curl-cffi.readthedocs.io/en/v0.12.0/quick_start.html "previous chapter") #### Next topic [What is TLS and http/2, http/3 fingerprinting?](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/fingerprint.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.12.0/_sources/impersonate/_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/impersonate/fingerprint.html "What is TLS and http/2, http/3 fingerprinting?") | * [previous](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/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/_index.html) --- # Cookies — curl_cffi documentation Cookies[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/cookies.html#cookies "Link to this heading") ==================================================================================================== How to save and load cookies[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/cookies.html#how-to-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. [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.11.1/index.html) ===================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.11.1/impersonate.html "previous chapter") * Next: [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.11.1/advanced.html "next chapter") --- # Cookies — curl_cffi documentation Cookies[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/cookies.html#cookies "Link to this heading") =================================================================================================== How to save and load cookies[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/cookies.html#how-to-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. import pickle \# import httpx from curl\_cffi import requests def save\_cookies(client): with open("cookies.pk", "wb") as f: pickle.dump(client.cookies.jar, 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 \= requests.Session(cookies\=load\_cookies()) save\_cookies(client) [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.1/index.html) ==================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.7.1/impersonate.html "previous chapter") * Next: [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.7.1/advanced.html "next chapter") ### Quick search --- # Advanced Usage — curl_cffi documentation Advanced Usage[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/advanced.html#advanced-usage "Link to this heading") =================================================================================================================== Low-level curl API[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/advanced.html#low-level-curl-api "Link to this heading") --------------------------------------------------------------------------------------------------------------------------- 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("chrome124") c.perform() c.close() body \= buffer.getvalue() print(body.decode()) Scrapy integrations[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/advanced.html#scrapy-integrations "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------- If you are using scrapy, check out these middlewares: * \[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/v0.11.0/advanced.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/v0.11.0/advanced.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/v0.11.0/advanced.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} )) Keeping session alive in http/2[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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() [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.11.0/index.html) ===================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Cookies](https://curl-cffi.readthedocs.io/en/v0.11.0/cookies.html "previous chapter") * Next: [Exceptions](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html "next chapter") --- # Advanced Usage — curl_cffi documentation Advanced Usage[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/advanced.html#advanced-usage "Link to this heading") =================================================================================================================== Low-level curl API[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/advanced.html#low-level-curl-api "Link to this heading") --------------------------------------------------------------------------------------------------------------------------- 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("chrome124") c.perform() c.close() body \= buffer.getvalue() print(body.decode()) Scrapy integrations[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/advanced.html#scrapy-integrations "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------- If you are using scrapy, check out these middlewares: * \[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/v0.10.0/advanced.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/v0.10.0/advanced.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/v0.10.0/advanced.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} )) [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.10.0/index.html) ===================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Cookies](https://curl-cffi.readthedocs.io/en/v0.10.0/cookies.html "previous chapter") * Next: [Exceptions](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html "next chapter") --- # Advanced Usage — curl_cffi documentation Advanced Usage[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/advanced.html#advanced-usage "Link to this heading") =================================================================================================================== Low-level curl API[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/advanced.html#low-level-curl-api "Link to this heading") --------------------------------------------------------------------------------------------------------------------------- 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("chrome124") c.perform() c.close() body \= buffer.getvalue() print(body.decode()) Scrapy integrations[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/advanced.html#scrapy-integrations "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------- If you are using scrapy, check out these middlewares: * \[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/v0.11.2/advanced.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/v0.11.2/advanced.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/v0.11.2/advanced.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} )) Keeping session alive in http/2[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/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() [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.11.2/index.html) ===================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Cookies](https://curl-cffi.readthedocs.io/en/v0.11.2/cookies.html "previous chapter") * Next: [Exceptions](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html "next chapter") --- # Supported browser impersonate targets — 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/impersonate/customize.html "How to use my own fingerprints? e.g. okhttp") | * [previous](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/fingerprint.html "What is TLS and http/2, http/3 fingerprinting?") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.13.0/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/_index.html) » * [Supported browser impersonate targets](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/targets.html) Supported browser impersonate targets[¶](https://curl-cffi.readthedocs.io/en/v0.13.0/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/v0.13.0/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/v0.13.0/index.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) #### Previous topic [What is TLS and http/2, http/3 fingerprinting?](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/fingerprint.html "previous chapter") #### Next topic [How to use my own fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/customize.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.13.0/_sources/impersonate/targets.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/impersonate/customize.html "How to use my own fingerprints? e.g. okhttp") | * [previous](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/fingerprint.html "What is TLS and http/2, http/3 fingerprinting?") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.13.0/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/_index.html) » * [Supported browser impersonate targets](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/targets.html) --- # Advanced Topics — 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/vs-requests.html "Compatibility with requests") | * [previous](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.html "Impersonate Guide") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.4/index.html) » * [Advanced Topics](https://curl-cffi.readthedocs.io/en/v0.11.4/advanced.html) Advanced Topics[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/advanced.html#advanced-topics "Link to this heading") ===================================================================================================================== Proxies[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/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 Use the proxies dict, only when you do have different proxies for http and https Low-level curl API[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/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/v0.11.4/api.html) Using `CURLOPT_*` in requests API[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/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/v0.11.4/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/v0.11.4/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/v0.11.4/index.html) * [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) #### Previous topic [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.html "previous chapter") #### Next topic [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.11.4/vs-requests.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.11.4/_sources/advanced.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/vs-requests.html "Compatibility with requests") | * [previous](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.html "Impersonate Guide") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.4/index.html) » * [Advanced Topics](https://curl-cffi.readthedocs.io/en/v0.11.4/advanced.html) --- # Advanced Topics — 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/vs-requests.html "Compatibility with requests") | * [previous](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.html "Impersonate Guide") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.3/index.html) » * [Advanced Topics](https://curl-cffi.readthedocs.io/en/v0.11.3/advanced.html) Advanced Topics[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/advanced.html#advanced-topics "Link to this heading") ===================================================================================================================== Proxies[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/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 Use the proxies dict, only when you do have different proxies for http and https Low-level curl API[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/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/v0.11.3/api.html) Using `CURLOPT_*` in requests API[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/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/v0.11.3/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/v0.11.3/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/v0.11.3/index.html) * [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) #### Previous topic [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.html "previous chapter") #### Next topic [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.11.3/vs-requests.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.11.3/_sources/advanced.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/vs-requests.html "Compatibility with requests") | * [previous](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.html "Impersonate Guide") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.3/index.html) » * [Advanced Topics](https://curl-cffi.readthedocs.io/en/v0.11.3/advanced.html) --- # Compatibility with requests — 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/cookies.html "Cookies") | * [previous](https://curl-cffi.readthedocs.io/en/v0.11.3/advanced.html "Advanced Topics") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.3/index.html) » * [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.11.3/vs-requests.html) Compatibility with requests[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/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/v0.11.3/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/v0.11.3/index.html) * [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) #### Previous topic [Advanced Topics](https://curl-cffi.readthedocs.io/en/v0.11.3/advanced.html "previous chapter") #### Next topic [Cookies](https://curl-cffi.readthedocs.io/en/v0.11.3/cookies.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.11.3/_sources/vs-requests.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/cookies.html "Cookies") | * [previous](https://curl-cffi.readthedocs.io/en/v0.11.3/advanced.html "Advanced Topics") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.3/index.html) » * [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.11.3/vs-requests.html) --- # Impersonate Guide — 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/advanced.html "Advanced Topics") | * [previous](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/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.html) Impersonate Guide[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.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`. 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 "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ### TLS and http/2[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.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/v0.11.4/impersonate.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`. Supported browser impersonate targets[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.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 * 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` Which target version to use?[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.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. 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 "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/v0.11.4/impersonate.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/v0.11.4/impersonate.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/v0.11.4/impersonate.html#id2) . ### How to toggle firefox-specific extensions?[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.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) 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 "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/v0.11.4/impersonate.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/v0.11.4/impersonate.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/v0.11.4/impersonate.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/v0.11.4/impersonate.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 look like Windows, just update the user-agent related headers to Windows. ### [Table of Contents](https://curl-cffi.readthedocs.io/en/v0.11.4/index.html) * [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) * [TLS and http/2](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.html#tls-and-http-2) * [http/3](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.html#http-3) * [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) * [JA3 and Akamai String Format](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.html#ja3-and-akamai-string-format) * [Using CURLOPTs](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.html#using-curlopts) * [How to toggle firefox-specific extensions?](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.html#how-to-toggle-firefox-specific-extensions) * [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) #### Previous topic [Quick Start](https://curl-cffi.readthedocs.io/en/v0.11.4/quick_start.html "previous chapter") #### Next topic [Advanced Topics](https://curl-cffi.readthedocs.io/en/v0.11.4/advanced.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.11.4/_sources/impersonate.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/advanced.html "Advanced Topics") | * [previous](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/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.11.4/impersonate.html) --- # Impersonate Guide — 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/advanced.html "Advanced Topics") | * [previous](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/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.html) Impersonate Guide[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.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`. 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 "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ### TLS and http/2[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.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/v0.11.3/impersonate.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`. Supported browser impersonate targets[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.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 * 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` Which target version to use?[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.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. 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 "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/v0.11.3/impersonate.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/v0.11.3/impersonate.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/v0.11.3/impersonate.html#id2) . ### How to toggle firefox-specific extensions?[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.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) 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 "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/v0.11.3/impersonate.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 pro version. 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 "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/v0.11.3/impersonate.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. ### [Table of Contents](https://curl-cffi.readthedocs.io/en/v0.11.3/index.html) * [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) * [TLS and http/2](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.html#tls-and-http-2) * [http/3](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.html#http-3) * [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) * [JA3 and Akamai String Format](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.html#ja3-and-akamai-string-format) * [Using CURLOPTs](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.html#using-curlopts) * [How to toggle firefox-specific extensions?](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.html#how-to-toggle-firefox-specific-extensions) * [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) #### Previous topic [Quick Start](https://curl-cffi.readthedocs.io/en/v0.11.3/quick_start.html "previous chapter") #### Next topic [Advanced Topics](https://curl-cffi.readthedocs.io/en/v0.11.3/advanced.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.11.3/_sources/impersonate.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/advanced.html "Advanced Topics") | * [previous](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/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.11.3/impersonate.html) --- # Cookies — curl_cffi documentation Cookies[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/cookies.html#cookies "Link to this heading") =================================================================================================== How to save and load cookies[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/cookies.html#how-to-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 from curl\_cffi import requests 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 \= requests.Session() client.get("https://httpbin.org/cookies/set/foo/bar") save\_cookies(client) client \= requests.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. [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.2/index.html) ==================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Impersonate guide](https://curl-cffi.readthedocs.io/en/v0.7.2/impersonate.html "previous chapter") * Next: [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.7.2/advanced.html "next chapter") --- # Advanced Usage — curl_cffi documentation Advanced Usage[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/advanced.html#advanced-usage "Link to this heading") ================================================================================================================== low-level curl API[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/advanced.html#low-level-curl-api "Link to this heading") -------------------------------------------------------------------------------------------------------------------------- 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("chrome124") c.perform() c.close() body \= buffer.getvalue() print(body.decode()) scrapy integrations[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/advanced.html#scrapy-integrations "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------- If you are using scrapy, check out these middlewares: * \[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/v0.7.2/advanced.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) [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.2/index.html) ==================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Cookies](https://curl-cffi.readthedocs.io/en/v0.7.2/cookies.html "previous chapter") * Next: [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.7.2/vs-requests.html "next chapter") --- # Advanced Usage — curl_cffi documentation Advanced Usage[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/advanced.html#advanced-usage "Link to this heading") ================================================================================================================== low-level curl API[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/advanced.html#low-level-curl-api "Link to this heading") -------------------------------------------------------------------------------------------------------------------------- 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("chrome124") c.perform() c.close() body \= buffer.getvalue() print(body.decode()) scrapy integrations[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/advanced.html#scrapy-integrations "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------- If you are using scrapy, check out these middlewares: * \[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/v0.7.0/advanced.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) [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.0/index.html) ==================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Cookies](https://curl-cffi.readthedocs.io/en/v0.7.0/cookies.html "previous chapter") * Next: [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.7.0/vs-requests.html "next chapter") ### Quick search --- # Advanced Usage — curl_cffi documentation Advanced Usage[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/advanced.html#advanced-usage "Link to this heading") =================================================================================================================== Low-level curl API[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/advanced.html#low-level-curl-api "Link to this heading") --------------------------------------------------------------------------------------------------------------------------- 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("chrome124") c.perform() c.close() body \= buffer.getvalue() print(body.decode()) Scrapy integrations[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/advanced.html#scrapy-integrations "Link to this heading") ----------------------------------------------------------------------------------------------------------------------------- If you are using scrapy, check out these middlewares: * \[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/v0.11.1/advanced.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/v0.11.1/advanced.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/v0.11.1/advanced.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} )) Keeping session alive in http/2[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/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() [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.11.1/index.html) ===================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Cookies](https://curl-cffi.readthedocs.io/en/v0.11.1/cookies.html "previous chapter") * Next: [Exceptions](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html "next chapter") --- # Advanced Usage — curl_cffi documentation Advanced Usage[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/advanced.html#advanced-usage "Link to this heading") ================================================================================================================== low-level curl API[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/advanced.html#low-level-curl-api "Link to this heading") -------------------------------------------------------------------------------------------------------------------------- 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("chrome124") c.perform() c.close() body \= buffer.getvalue() print(body.decode()) scrapy integrations[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/advanced.html#scrapy-integrations "Link to this heading") ---------------------------------------------------------------------------------------------------------------------------- If you are using scrapy, check out these middlewares: * \[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/v0.7.1/advanced.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) [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.1/index.html) ==================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Cookies](https://curl-cffi.readthedocs.io/en/v0.7.1/cookies.html "previous chapter") * Next: [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.7.1/vs-requests.html "next chapter") ### Quick search --- # Compatibility with requests — 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/cookies.html "Cookies") | * [previous](https://curl-cffi.readthedocs.io/en/v0.11.4/advanced.html "Advanced Topics") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.4/index.html) » * [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.11.4/vs-requests.html) Compatibility with requests[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/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/v0.11.4/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/v0.11.4/index.html) * [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) #### Previous topic [Advanced Topics](https://curl-cffi.readthedocs.io/en/v0.11.4/advanced.html "previous chapter") #### Next topic [Cookies](https://curl-cffi.readthedocs.io/en/v0.11.4/cookies.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.11.4/_sources/vs-requests.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/cookies.html "Cookies") | * [previous](https://curl-cffi.readthedocs.io/en/v0.11.4/advanced.html "Advanced Topics") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.4/index.html) » * [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.11.4/vs-requests.html) --- # Supported browser impersonate targets — 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/impersonate/customize.html "How to use my own fingerprints? e.g. okhttp") | * [previous](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/fingerprint.html "What is TLS and http/2, http/3 fingerprinting?") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.12.0/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/_index.html) » * [Supported browser impersonate targets](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/targets.html) Supported browser impersonate targets[¶](https://curl-cffi.readthedocs.io/en/v0.12.0/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/v0.12.0/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/v0.12.0/index.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) #### Previous topic [What is TLS and http/2, http/3 fingerprinting?](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/fingerprint.html "previous chapter") #### Next topic [How to use my own fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/customize.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.12.0/_sources/impersonate/targets.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/impersonate/customize.html "How to use my own fingerprints? e.g. okhttp") | * [previous](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/fingerprint.html "What is TLS and http/2, http/3 fingerprinting?") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.12.0/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/_index.html) » * [Supported browser impersonate targets](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/targets.html) --- # Compatibility with requests — curl_cffi documentation Compatibility with requests[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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) ) [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.2/index.html) ==================================================================== ### 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/index.html) * Previous: [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.7.2/advanced.html "previous chapter") * Next: [FAQ](https://curl-cffi.readthedocs.io/en/v0.7.2/faq.html "next chapter") --- # How to use my own fingerprints? e.g. okhttp — 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/impersonate/psk.html "TLS PSK(41) Extension") | * [previous](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/targets.html "Supported browser impersonate targets") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.13.0/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/_index.html) » * [How to use my own fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/customize.html) How to use my own fingerprints? e.g. okhttp[¶](https://curl-cffi.readthedocs.io/en/v0.13.0/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/v0.13.0/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/v0.13.0/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/v0.13.0/impersonate/customize.html#id1) . How to toggle firefox-specific extensions?[¶](https://curl-cffi.readthedocs.io/en/v0.13.0/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/v0.13.0/index.html) * [How to use my own fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/customize.html#) * [JA3 and Akamai String Format](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/customize.html#ja3-and-akamai-string-format) * [Using CURLOPTs](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/customize.html#using-curlopts) * [How to toggle firefox-specific extensions?](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/customize.html#how-to-toggle-firefox-specific-extensions) #### Previous topic [Supported browser impersonate targets](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/targets.html "previous chapter") #### Next topic [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/psk.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.13.0/_sources/impersonate/customize.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/impersonate/psk.html "TLS PSK(41) Extension") | * [previous](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/targets.html "Supported browser impersonate targets") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.13.0/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/_index.html) » * [How to use my own fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/customize.html) --- # Compatibility with requests — curl_cffi documentation Compatibility with requests[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/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. Alternatively, 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. [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.11.2/index.html) ===================================================================== ### 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/index.html) * Previous: [Exceptions](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html "previous chapter") * Next: [FAQ](https://curl-cffi.readthedocs.io/en/v0.11.2/faq.html "next chapter") --- # Compatibility with requests — curl_cffi documentation Compatibility with requests[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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/yifeikong/curl\_cffi/issues/24](https://github.com/yifeikong/curl_cffi/issues/24) ) * redirect history are not supported, tracked in \[#82\]([https://github.com/yifeikong/curl\_cffi/issues/82](https://github.com/yifeikong/curl_cffi/issues/82) ) * empty-domains cookies may lost during redirects, tracked in \[#55\]([https://github.com/yifeikong/curl\_cffi/issues/55](https://github.com/yifeikong/curl_cffi/issues/55) ) [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.1/index.html) ==================================================================== ### 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/index.html) * Previous: [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.7.1/advanced.html "previous chapter") * Next: [FAQ](https://curl-cffi.readthedocs.io/en/v0.7.1/faq.html "next chapter") ### Quick search --- # Compatibility with requests — curl_cffi documentation Compatibility with requests[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/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) ) Alternatively, 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. [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.10.0/index.html) ===================================================================== ### 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/index.html) * Previous: [Exceptions](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html "previous chapter") * Next: [FAQ](https://curl-cffi.readthedocs.io/en/v0.10.0/faq.html "next chapter") --- # Community — 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/api.html "API References") | * [previous](https://curl-cffi.readthedocs.io/en/v0.11.3/cookies.html "Cookies") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.3/index.html) » * [Community](https://curl-cffi.readthedocs.io/en/v0.11.3/community.html) Community[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/community.html#community "Link to this heading") ========================================================================================================== Scrapy integrations[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/community.html#scrapy-integrations "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------ If you are using scrapy, check out these middlewares: * \[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/v0.11.3/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/v0.11.3/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/v0.11.3/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/v0.11.3/index.html) * [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) #### Previous topic [Cookies](https://curl-cffi.readthedocs.io/en/v0.11.3/cookies.html "previous chapter") #### Next topic [API References](https://curl-cffi.readthedocs.io/en/v0.11.3/api.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.11.3/_sources/community.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/api.html "API References") | * [previous](https://curl-cffi.readthedocs.io/en/v0.11.3/cookies.html "Cookies") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.3/index.html) » * [Community](https://curl-cffi.readthedocs.io/en/v0.11.3/community.html) --- # Cookies — 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/community.html "Community") | * [previous](https://curl-cffi.readthedocs.io/en/v0.11.3/vs-requests.html "Compatibility with requests") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.3/index.html) » * [Cookies](https://curl-cffi.readthedocs.io/en/v0.11.3/cookies.html) Cookies[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/cookies.html#cookies "Link to this heading") ==================================================================================================== Save and load cookies[¶](https://curl-cffi.readthedocs.io/en/v0.11.3/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/v0.11.3/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/v0.11.3/index.html) * [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) #### Previous topic [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.11.3/vs-requests.html "previous chapter") #### Next topic [Community](https://curl-cffi.readthedocs.io/en/v0.11.3/community.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.11.3/_sources/cookies.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/community.html "Community") | * [previous](https://curl-cffi.readthedocs.io/en/v0.11.3/vs-requests.html "Compatibility with requests") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.3/index.html) » * [Cookies](https://curl-cffi.readthedocs.io/en/v0.11.3/cookies.html) --- # Exceptions — curl_cffi documentation Exceptions[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#exceptions "Link to this heading") ============================================================================================================= We try to follow the requests exception hirearchy, however, some are missing, while some are added. If an exception is marked as “not used”, please catch the base exception. Exceptions[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#id1 "Link to this heading") ------------------------------------------------------------------------------------------------------ _class_ curl\_cffi.requests.exceptions.RequestException(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#RequestException) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.RequestException "Link to this definition") Base exception for curl\_cffi.requests package _class_ curl\_cffi.requests.exceptions.CookieConflict(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#CookieConflict) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.CookieConflict "Link to this definition") Same cookie exists for different domains. _class_ curl\_cffi.requests.exceptions.SessionClosed(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#SessionClosed) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.SessionClosed "Link to this definition") The session has already been closed. _class_ curl\_cffi.requests.exceptions.ImpersonateError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#ImpersonateError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.ImpersonateError "Link to this definition") The impersonate config was wrong or impersonate failed. _class_ curl\_cffi.requests.exceptions.InvalidJSONError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#InvalidJSONError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.InvalidJSONError "Link to this definition") A JSON error occurred. not used _class_ curl\_cffi.requests.exceptions.HTTPError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#HTTPError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.HTTPError "Link to this definition") An HTTP error occurred. _class_ curl\_cffi.requests.exceptions.IncompleteRead(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#IncompleteRead) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.IncompleteRead "Link to this definition") Incomplete read of content _class_ curl\_cffi.requests.exceptions.ConnectionError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#ConnectionError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.ConnectionError "Link to this definition") A Connection error occurred. _class_ curl\_cffi.requests.exceptions.DNSError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#DNSError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.DNSError "Link to this definition") Could not resolve _class_ curl\_cffi.requests.exceptions.ProxyError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#ProxyError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.ProxyError "Link to this definition") A proxy error occurred. _class_ curl\_cffi.requests.exceptions.SSLError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#SSLError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.SSLError "Link to this definition") An SSL error occurred. _class_ curl\_cffi.requests.exceptions.CertificateVerifyError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#CertificateVerifyError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.CertificateVerifyError "Link to this definition") Raised when certificate validated has failed _class_ curl\_cffi.requests.exceptions.Timeout(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#Timeout) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.Timeout "Link to this definition") The request timed out. _class_ curl\_cffi.requests.exceptions.ConnectTimeout(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#ConnectTimeout) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.ConnectTimeout "Link to this definition") The request timed out while trying to connect to the remote server. Requests that produced this error are safe to retry. not used _class_ curl\_cffi.requests.exceptions.ReadTimeout(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#ReadTimeout) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.ReadTimeout "Link to this definition") The server did not send any data in the allotted amount of time. not used _class_ curl\_cffi.requests.exceptions.URLRequired(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#URLRequired) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.URLRequired "Link to this definition") A valid URL is required to make a request. not used _class_ curl\_cffi.requests.exceptions.TooManyRedirects(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#TooManyRedirects) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.TooManyRedirects "Link to this definition") Too many redirects. _class_ curl\_cffi.requests.exceptions.MissingSchema(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#MissingSchema) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.MissingSchema "Link to this definition") The URL scheme (e.g. http or https) is missing. not used _class_ curl\_cffi.requests.exceptions.InvalidSchema(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#InvalidSchema) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.InvalidSchema "Link to this definition") The URL scheme provided is either invalid or unsupported. not used _class_ curl\_cffi.requests.exceptions.InvalidURL(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#InvalidURL) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.InvalidURL "Link to this definition") The URL provided was somehow invalid. _class_ curl\_cffi.requests.exceptions.InvalidHeader(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#InvalidHeader) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.InvalidHeader "Link to this definition") The header value provided was somehow invalid. not used _class_ curl\_cffi.requests.exceptions.InvalidProxyURL(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#InvalidProxyURL) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.InvalidProxyURL "Link to this definition") The proxy URL provided is invalid. not used _class_ curl\_cffi.requests.exceptions.ChunkedEncodingError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#ChunkedEncodingError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.ChunkedEncodingError "Link to this definition") The server declared chunked encoding but sent an invalid chunk. not used _class_ curl\_cffi.requests.exceptions.ContentDecodingError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#ContentDecodingError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.ContentDecodingError "Link to this definition") Failed to decode response content. not used _class_ curl\_cffi.requests.exceptions.StreamConsumedError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#StreamConsumedError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.StreamConsumedError "Link to this definition") The content for this response was already consumed. not used _class_ curl\_cffi.requests.exceptions.RetryError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#RetryError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.RetryError "Link to this definition") Custom retries logic failed. not used _class_ curl\_cffi.requests.exceptions.UnrewindableBodyError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#UnrewindableBodyError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.UnrewindableBodyError "Link to this definition") Requests encountered an error when trying to rewind a body. not used _class_ curl\_cffi.requests.exceptions.InterfaceError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#InterfaceError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.InterfaceError "Link to this definition") A specified outgoing interface could not be used. Warnings[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#warnings "Link to this heading") --------------------------------------------------------------------------------------------------------- _class_ curl\_cffi.requests.exceptions.RequestsWarning[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#RequestsWarning) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.RequestsWarning "Link to this definition") Base warning for Requests. not used _class_ curl\_cffi.requests.exceptions.FileModeWarning[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#FileModeWarning) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.FileModeWarning "Link to this definition") A file was opened in text mode, but Requests determined its binary length. not used _class_ curl\_cffi.requests.exceptions.RequestsDependencyWarning[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/exceptions.html#RequestsDependencyWarning) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html#curl_cffi.requests.exceptions.RequestsDependencyWarning "Link to this definition") An imported dependency doesn’t match the expected version range. [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.11.0/index.html) ===================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.11.0/advanced.html "previous chapter") * Next: [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.11.0/vs-requests.html "next chapter") --- # TLS PSK(41) Extension — 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/impersonate/faq.html "Impersonation FAQ") | * [previous](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/customize.html "How to use my own fingerprints? e.g. okhttp") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.13.0/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/_index.html) » * [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/psk.html) TLS PSK(41) Extension[¶](https://curl-cffi.readthedocs.io/en/v0.13.0/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/v0.13.0/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/v0.13.0/index.html) * [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/psk.html#) * [How do I enable PSK extension anyway?](https://curl-cffi.readthedocs.io/en/v0.13.0/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/v0.13.0/impersonate/customize.html "previous chapter") #### Next topic [Impersonation FAQ](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/faq.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.13.0/_sources/impersonate/psk.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/impersonate/faq.html "Impersonation FAQ") | * [previous](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/customize.html "How to use my own fingerprints? e.g. okhttp") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.13.0/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/_index.html) » * [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/psk.html) --- # How to use my own fingerprints? e.g. okhttp — 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/impersonate/psk.html "TLS PSK(41) Extension") | * [previous](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/targets.html "Supported browser impersonate targets") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.12.0/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/_index.html) » * [How to use my own fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/customize.html) How to use my own fingerprints? e.g. okhttp[¶](https://curl-cffi.readthedocs.io/en/v0.12.0/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/v0.12.0/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/v0.12.0/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/v0.12.0/impersonate/customize.html#id1) . How to toggle firefox-specific extensions?[¶](https://curl-cffi.readthedocs.io/en/v0.12.0/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/v0.12.0/index.html) * [How to use my own fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/customize.html#) * [JA3 and Akamai String Format](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/customize.html#ja3-and-akamai-string-format) * [Using CURLOPTs](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/customize.html#using-curlopts) * [How to toggle firefox-specific extensions?](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/customize.html#how-to-toggle-firefox-specific-extensions) #### Previous topic [Supported browser impersonate targets](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/targets.html "previous chapter") #### Next topic [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/psk.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.12.0/_sources/impersonate/customize.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/impersonate/psk.html "TLS PSK(41) Extension") | * [previous](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/targets.html "Supported browser impersonate targets") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.12.0/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/_index.html) » * [How to use my own fingerprints? e.g. okhttp](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/customize.html) --- # Exceptions — curl_cffi documentation Exceptions[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#exceptions "Link to this heading") ============================================================================================================= We try to follow the requests exception hirearchy, however, some are missing, while some are added. If an exception is marked as “not used”, please catch the base exception. Exceptions[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#id1 "Link to this heading") ------------------------------------------------------------------------------------------------------ _class_ curl\_cffi.requests.exceptions.RequestException(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#RequestException) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.RequestException "Link to this definition") Base exception for curl\_cffi.requests package _class_ curl\_cffi.requests.exceptions.CookieConflict(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#CookieConflict) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.CookieConflict "Link to this definition") Same cookie exists for different domains. _class_ curl\_cffi.requests.exceptions.SessionClosed(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#SessionClosed) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.SessionClosed "Link to this definition") The session has already been closed. _class_ curl\_cffi.requests.exceptions.ImpersonateError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#ImpersonateError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.ImpersonateError "Link to this definition") The impersonate config was wrong or impersonate failed. _class_ curl\_cffi.requests.exceptions.InvalidJSONError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#InvalidJSONError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.InvalidJSONError "Link to this definition") A JSON error occurred. not used _class_ curl\_cffi.requests.exceptions.HTTPError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#HTTPError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.HTTPError "Link to this definition") An HTTP error occurred. _class_ curl\_cffi.requests.exceptions.IncompleteRead(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#IncompleteRead) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.IncompleteRead "Link to this definition") Incomplete read of content _class_ curl\_cffi.requests.exceptions.ConnectionError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#ConnectionError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.ConnectionError "Link to this definition") A Connection error occurred. _class_ curl\_cffi.requests.exceptions.DNSError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#DNSError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.DNSError "Link to this definition") Could not resolve _class_ curl\_cffi.requests.exceptions.ProxyError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#ProxyError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.ProxyError "Link to this definition") A proxy error occurred. _class_ curl\_cffi.requests.exceptions.SSLError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#SSLError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.SSLError "Link to this definition") An SSL error occurred. _class_ curl\_cffi.requests.exceptions.CertificateVerifyError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#CertificateVerifyError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.CertificateVerifyError "Link to this definition") Raised when certificate validated has failed _class_ curl\_cffi.requests.exceptions.Timeout(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#Timeout) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.Timeout "Link to this definition") The request timed out. _class_ curl\_cffi.requests.exceptions.ConnectTimeout(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#ConnectTimeout) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.ConnectTimeout "Link to this definition") The request timed out while trying to connect to the remote server. Requests that produced this error are safe to retry. not used _class_ curl\_cffi.requests.exceptions.ReadTimeout(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#ReadTimeout) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.ReadTimeout "Link to this definition") The server did not send any data in the allotted amount of time. not used _class_ curl\_cffi.requests.exceptions.URLRequired(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#URLRequired) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.URLRequired "Link to this definition") A valid URL is required to make a request. not used _class_ curl\_cffi.requests.exceptions.TooManyRedirects(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#TooManyRedirects) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.TooManyRedirects "Link to this definition") Too many redirects. _class_ curl\_cffi.requests.exceptions.MissingSchema(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#MissingSchema) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.MissingSchema "Link to this definition") The URL scheme (e.g. http or https) is missing. not used _class_ curl\_cffi.requests.exceptions.InvalidSchema(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#InvalidSchema) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.InvalidSchema "Link to this definition") The URL scheme provided is either invalid or unsupported. not used _class_ curl\_cffi.requests.exceptions.InvalidURL(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#InvalidURL) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.InvalidURL "Link to this definition") The URL provided was somehow invalid. _class_ curl\_cffi.requests.exceptions.InvalidHeader(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#InvalidHeader) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.InvalidHeader "Link to this definition") The header value provided was somehow invalid. not used _class_ curl\_cffi.requests.exceptions.InvalidProxyURL(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#InvalidProxyURL) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.InvalidProxyURL "Link to this definition") The proxy URL provided is invalid. not used _class_ curl\_cffi.requests.exceptions.ChunkedEncodingError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#ChunkedEncodingError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.ChunkedEncodingError "Link to this definition") The server declared chunked encoding but sent an invalid chunk. not used _class_ curl\_cffi.requests.exceptions.ContentDecodingError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#ContentDecodingError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.ContentDecodingError "Link to this definition") Failed to decode response content. not used _class_ curl\_cffi.requests.exceptions.StreamConsumedError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#StreamConsumedError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.StreamConsumedError "Link to this definition") The content for this response was already consumed. not used _class_ curl\_cffi.requests.exceptions.RetryError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#RetryError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.RetryError "Link to this definition") Custom retries logic failed. not used _class_ curl\_cffi.requests.exceptions.UnrewindableBodyError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#UnrewindableBodyError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.UnrewindableBodyError "Link to this definition") Requests encountered an error when trying to rewind a body. not used _class_ curl\_cffi.requests.exceptions.InterfaceError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#InterfaceError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.InterfaceError "Link to this definition") A specified outgoing interface could not be used. Warnings[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#warnings "Link to this heading") --------------------------------------------------------------------------------------------------------- _class_ curl\_cffi.requests.exceptions.RequestsWarning[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#RequestsWarning) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.RequestsWarning "Link to this definition") Base warning for Requests. not used _class_ curl\_cffi.requests.exceptions.FileModeWarning[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#FileModeWarning) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.FileModeWarning "Link to this definition") A file was opened in text mode, but Requests determined its binary length. not used _class_ curl\_cffi.requests.exceptions.RequestsDependencyWarning[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.2/_modules/curl_cffi/requests/exceptions.html#RequestsDependencyWarning) [¶](https://curl-cffi.readthedocs.io/en/v0.11.2/exceptions.html#curl_cffi.requests.exceptions.RequestsDependencyWarning "Link to this definition") An imported dependency doesn’t match the expected version range. [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.11.2/index.html) ===================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.11.2/advanced.html "previous chapter") * Next: [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.11.2/vs-requests.html "next chapter") --- # Cookies — 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/community.html "Community") | * [previous](https://curl-cffi.readthedocs.io/en/v0.11.4/vs-requests.html "Compatibility with requests") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.4/index.html) » * [Cookies](https://curl-cffi.readthedocs.io/en/v0.11.4/cookies.html) Cookies[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/cookies.html#cookies "Link to this heading") ==================================================================================================== Save and load cookies[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/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/v0.11.4/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/v0.11.4/index.html) * [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) #### Previous topic [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.11.4/vs-requests.html "previous chapter") #### Next topic [Community](https://curl-cffi.readthedocs.io/en/v0.11.4/community.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.11.4/_sources/cookies.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/community.html "Community") | * [previous](https://curl-cffi.readthedocs.io/en/v0.11.4/vs-requests.html "Compatibility with requests") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.4/index.html) » * [Cookies](https://curl-cffi.readthedocs.io/en/v0.11.4/cookies.html) --- # Community — 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/api.html "API References") | * [previous](https://curl-cffi.readthedocs.io/en/v0.11.4/cookies.html "Cookies") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.4/index.html) » * [Community](https://curl-cffi.readthedocs.io/en/v0.11.4/community.html) Community[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/community.html#community "Link to this heading") ========================================================================================================== Scrapy integrations[¶](https://curl-cffi.readthedocs.io/en/v0.11.4/community.html#scrapy-integrations "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------ If you are using scrapy, check out these middlewares: * \[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/v0.11.4/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/v0.11.4/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/v0.11.4/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/v0.11.4/index.html) * [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) #### Previous topic [Cookies](https://curl-cffi.readthedocs.io/en/v0.11.4/cookies.html "previous chapter") #### Next topic [API References](https://curl-cffi.readthedocs.io/en/v0.11.4/api.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.11.4/_sources/community.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/api.html "API References") | * [previous](https://curl-cffi.readthedocs.io/en/v0.11.4/cookies.html "Cookies") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.11.4/index.html) » * [Community](https://curl-cffi.readthedocs.io/en/v0.11.4/community.html) --- # Compatibility with requests — curl_cffi documentation Compatibility with requests[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/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. Alternatively, 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. [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.11.1/index.html) ===================================================================== ### 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/index.html) * Previous: [Exceptions](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html "previous chapter") * Next: [FAQ](https://curl-cffi.readthedocs.io/en/v0.11.1/faq.html "next chapter") --- # TLS PSK(41) Extension — 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/impersonate/faq.html "Impersonation FAQ") | * [previous](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/customize.html "How to use my own fingerprints? e.g. okhttp") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.12.0/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/_index.html) » * [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/psk.html) TLS PSK(41) Extension[¶](https://curl-cffi.readthedocs.io/en/v0.12.0/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/v0.12.0/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/v0.12.0/index.html) * [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/psk.html#) * [How do I enable PSK extension anyway?](https://curl-cffi.readthedocs.io/en/v0.12.0/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/v0.12.0/impersonate/customize.html "previous chapter") #### Next topic [Impersonation FAQ](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/faq.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.12.0/_sources/impersonate/psk.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/impersonate/faq.html "Impersonation FAQ") | * [previous](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/customize.html "How to use my own fingerprints? e.g. okhttp") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.12.0/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/_index.html) » * [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/v0.12.0/impersonate/psk.html) --- # Exceptions — curl_cffi documentation Exceptions[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#exceptions "Link to this heading") ============================================================================================================= We try to follow the requests exception hirearchy, however, some are missing, while some are added. If an exception is marked as “not used”, please catch the base exception. Exceptions[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#id1 "Link to this heading") ------------------------------------------------------------------------------------------------------ _class_ curl\_cffi.requests.exceptions.RequestException(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#RequestException) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.RequestException "Link to this definition") Base exception for curl\_cffi.requests package _class_ curl\_cffi.requests.exceptions.CookieConflict(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#CookieConflict) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.CookieConflict "Link to this definition") Same cookie exists for different domains. _class_ curl\_cffi.requests.exceptions.SessionClosed(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#SessionClosed) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.SessionClosed "Link to this definition") The session has already been closed. _class_ curl\_cffi.requests.exceptions.ImpersonateError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#ImpersonateError) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.ImpersonateError "Link to this definition") The impersonate config was wrong or impersonate failed. _class_ curl\_cffi.requests.exceptions.InvalidJSONError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#InvalidJSONError) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.InvalidJSONError "Link to this definition") A JSON error occurred. not used _class_ curl\_cffi.requests.exceptions.HTTPError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#HTTPError) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.HTTPError "Link to this definition") An HTTP error occurred. _class_ curl\_cffi.requests.exceptions.IncompleteRead(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#IncompleteRead) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.IncompleteRead "Link to this definition") Incomplete read of content _class_ curl\_cffi.requests.exceptions.ConnectionError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#ConnectionError) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.ConnectionError "Link to this definition") A Connection error occurred. _class_ curl\_cffi.requests.exceptions.DNSError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#DNSError) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.DNSError "Link to this definition") Could not resolve _class_ curl\_cffi.requests.exceptions.ProxyError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#ProxyError) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.ProxyError "Link to this definition") A proxy error occurred. _class_ curl\_cffi.requests.exceptions.SSLError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#SSLError) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.SSLError "Link to this definition") An SSL error occurred. _class_ curl\_cffi.requests.exceptions.CertificateVerifyError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#CertificateVerifyError) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.CertificateVerifyError "Link to this definition") Raised when certificate validated has failed _class_ curl\_cffi.requests.exceptions.Timeout(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#Timeout) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.Timeout "Link to this definition") The request timed out. _class_ curl\_cffi.requests.exceptions.ConnectTimeout(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#ConnectTimeout) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.ConnectTimeout "Link to this definition") The request timed out while trying to connect to the remote server. Requests that produced this error are safe to retry. not used _class_ curl\_cffi.requests.exceptions.ReadTimeout(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#ReadTimeout) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.ReadTimeout "Link to this definition") The server did not send any data in the allotted amount of time. not used _class_ curl\_cffi.requests.exceptions.URLRequired(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#URLRequired) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.URLRequired "Link to this definition") A valid URL is required to make a request. not used _class_ curl\_cffi.requests.exceptions.TooManyRedirects(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#TooManyRedirects) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.TooManyRedirects "Link to this definition") Too many redirects. _class_ curl\_cffi.requests.exceptions.MissingSchema(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#MissingSchema) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.MissingSchema "Link to this definition") The URL scheme (e.g. http or https) is missing. not used _class_ curl\_cffi.requests.exceptions.InvalidSchema(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#InvalidSchema) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.InvalidSchema "Link to this definition") The URL scheme provided is either invalid or unsupported. not used _class_ curl\_cffi.requests.exceptions.InvalidURL(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#InvalidURL) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.InvalidURL "Link to this definition") The URL provided was somehow invalid. _class_ curl\_cffi.requests.exceptions.InvalidHeader(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#InvalidHeader) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.InvalidHeader "Link to this definition") The header value provided was somehow invalid. not used _class_ curl\_cffi.requests.exceptions.InvalidProxyURL(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#InvalidProxyURL) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.InvalidProxyURL "Link to this definition") The proxy URL provided is invalid. not used _class_ curl\_cffi.requests.exceptions.ChunkedEncodingError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#ChunkedEncodingError) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.ChunkedEncodingError "Link to this definition") The server declared chunked encoding but sent an invalid chunk. not used _class_ curl\_cffi.requests.exceptions.ContentDecodingError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#ContentDecodingError) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.ContentDecodingError "Link to this definition") Failed to decode response content. not used _class_ curl\_cffi.requests.exceptions.StreamConsumedError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#StreamConsumedError) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.StreamConsumedError "Link to this definition") The content for this response was already consumed. not used _class_ curl\_cffi.requests.exceptions.RetryError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#RetryError) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.RetryError "Link to this definition") Custom retries logic failed. not used _class_ curl\_cffi.requests.exceptions.UnrewindableBodyError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#UnrewindableBodyError) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.UnrewindableBodyError "Link to this definition") Requests encountered an error when trying to rewind a body. not used _class_ curl\_cffi.requests.exceptions.InterfaceError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#InterfaceError) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.InterfaceError "Link to this definition") A specified outgoing interface could not be used. Warnings[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#warnings "Link to this heading") --------------------------------------------------------------------------------------------------------- _class_ curl\_cffi.requests.exceptions.RequestsWarning[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#RequestsWarning) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.RequestsWarning "Link to this definition") Base warning for Requests. not used _class_ curl\_cffi.requests.exceptions.FileModeWarning[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#FileModeWarning) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.FileModeWarning "Link to this definition") A file was opened in text mode, but Requests determined its binary length. not used _class_ curl\_cffi.requests.exceptions.RequestsDependencyWarning[\[source\]](https://curl-cffi.readthedocs.io/en/v0.10.0/_modules/curl_cffi/requests/exceptions.html#RequestsDependencyWarning) [¶](https://curl-cffi.readthedocs.io/en/v0.10.0/exceptions.html#curl_cffi.requests.exceptions.RequestsDependencyWarning "Link to this definition") An imported dependency doesn’t match the expected version range. [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.10.0/index.html) ===================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.10.0/advanced.html "previous chapter") * Next: [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.10.0/vs-requests.html "next chapter") --- # Exceptions — curl_cffi documentation Exceptions[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#exceptions "Link to this heading") ============================================================================================================= We try to follow the requests exception hirearchy, however, some are missing, while some are added. If an exception is marked as “not used”, please catch the base exception. Exceptions[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#id1 "Link to this heading") ------------------------------------------------------------------------------------------------------ _class_ curl\_cffi.requests.exceptions.RequestException(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#RequestException) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.RequestException "Link to this definition") Base exception for curl\_cffi.requests package _class_ curl\_cffi.requests.exceptions.CookieConflict(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#CookieConflict) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.CookieConflict "Link to this definition") Same cookie exists for different domains. _class_ curl\_cffi.requests.exceptions.SessionClosed(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#SessionClosed) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.SessionClosed "Link to this definition") The session has already been closed. _class_ curl\_cffi.requests.exceptions.ImpersonateError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#ImpersonateError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.ImpersonateError "Link to this definition") The impersonate config was wrong or impersonate failed. _class_ curl\_cffi.requests.exceptions.InvalidJSONError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#InvalidJSONError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.InvalidJSONError "Link to this definition") A JSON error occurred. not used _class_ curl\_cffi.requests.exceptions.HTTPError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#HTTPError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.HTTPError "Link to this definition") An HTTP error occurred. _class_ curl\_cffi.requests.exceptions.IncompleteRead(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#IncompleteRead) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.IncompleteRead "Link to this definition") Incomplete read of content _class_ curl\_cffi.requests.exceptions.ConnectionError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#ConnectionError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.ConnectionError "Link to this definition") A Connection error occurred. _class_ curl\_cffi.requests.exceptions.DNSError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#DNSError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.DNSError "Link to this definition") Could not resolve _class_ curl\_cffi.requests.exceptions.ProxyError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#ProxyError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.ProxyError "Link to this definition") A proxy error occurred. _class_ curl\_cffi.requests.exceptions.SSLError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#SSLError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.SSLError "Link to this definition") An SSL error occurred. _class_ curl\_cffi.requests.exceptions.CertificateVerifyError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#CertificateVerifyError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.CertificateVerifyError "Link to this definition") Raised when certificate validated has failed _class_ curl\_cffi.requests.exceptions.Timeout(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#Timeout) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.Timeout "Link to this definition") The request timed out. _class_ curl\_cffi.requests.exceptions.ConnectTimeout(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#ConnectTimeout) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.ConnectTimeout "Link to this definition") The request timed out while trying to connect to the remote server. Requests that produced this error are safe to retry. not used _class_ curl\_cffi.requests.exceptions.ReadTimeout(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#ReadTimeout) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.ReadTimeout "Link to this definition") The server did not send any data in the allotted amount of time. not used _class_ curl\_cffi.requests.exceptions.URLRequired(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#URLRequired) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.URLRequired "Link to this definition") A valid URL is required to make a request. not used _class_ curl\_cffi.requests.exceptions.TooManyRedirects(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#TooManyRedirects) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.TooManyRedirects "Link to this definition") Too many redirects. _class_ curl\_cffi.requests.exceptions.MissingSchema(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#MissingSchema) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.MissingSchema "Link to this definition") The URL scheme (e.g. http or https) is missing. not used _class_ curl\_cffi.requests.exceptions.InvalidSchema(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#InvalidSchema) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.InvalidSchema "Link to this definition") The URL scheme provided is either invalid or unsupported. not used _class_ curl\_cffi.requests.exceptions.InvalidURL(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#InvalidURL) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.InvalidURL "Link to this definition") The URL provided was somehow invalid. _class_ curl\_cffi.requests.exceptions.InvalidHeader(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#InvalidHeader) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.InvalidHeader "Link to this definition") The header value provided was somehow invalid. not used _class_ curl\_cffi.requests.exceptions.InvalidProxyURL(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#InvalidProxyURL) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.InvalidProxyURL "Link to this definition") The proxy URL provided is invalid. not used _class_ curl\_cffi.requests.exceptions.ChunkedEncodingError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#ChunkedEncodingError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.ChunkedEncodingError "Link to this definition") The server declared chunked encoding but sent an invalid chunk. not used _class_ curl\_cffi.requests.exceptions.ContentDecodingError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#ContentDecodingError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.ContentDecodingError "Link to this definition") Failed to decode response content. not used _class_ curl\_cffi.requests.exceptions.StreamConsumedError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#StreamConsumedError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.StreamConsumedError "Link to this definition") The content for this response was already consumed. not used _class_ curl\_cffi.requests.exceptions.RetryError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#RetryError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.RetryError "Link to this definition") Custom retries logic failed. not used _class_ curl\_cffi.requests.exceptions.UnrewindableBodyError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#UnrewindableBodyError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.UnrewindableBodyError "Link to this definition") Requests encountered an error when trying to rewind a body. not used _class_ curl\_cffi.requests.exceptions.InterfaceError(_msg_, _code: [CurlECode](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html#curl_cffi.CurlECode "curl_cffi.const.CurlECode") | Literal\[0\] \= 0_, _response\=None_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#InterfaceError) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.InterfaceError "Link to this definition") A specified outgoing interface could not be used. Warnings[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#warnings "Link to this heading") --------------------------------------------------------------------------------------------------------- _class_ curl\_cffi.requests.exceptions.RequestsWarning[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#RequestsWarning) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.RequestsWarning "Link to this definition") Base warning for Requests. not used _class_ curl\_cffi.requests.exceptions.FileModeWarning[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#FileModeWarning) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.FileModeWarning "Link to this definition") A file was opened in text mode, but Requests determined its binary length. not used _class_ curl\_cffi.requests.exceptions.RequestsDependencyWarning[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.1/_modules/curl_cffi/requests/exceptions.html#RequestsDependencyWarning) [¶](https://curl-cffi.readthedocs.io/en/v0.11.1/exceptions.html#curl_cffi.requests.exceptions.RequestsDependencyWarning "Link to this definition") An imported dependency doesn’t match the expected version range. [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.11.1/index.html) ===================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.11.1/advanced.html "previous chapter") * Next: [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.11.1/vs-requests.html "next chapter") --- # Impersonation FAQ — 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/advanced.html "Advanced Topics") | * [previous](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/psk.html "TLS PSK(41) Extension") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.13.0/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/_index.html) » * [Impersonation FAQ](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/faq.html) Impersonation FAQ[¶](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/faq.html#impersonation-faq "Link to this heading") ================================================================================================================================ How to check if my impersonation is working?[¶](https://curl-cffi.readthedocs.io/en/v0.13.0/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/v0.13.0/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/v0.13.0/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/v0.13.0/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/v0.13.0/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/v0.13.0/index.html) * [Impersonation FAQ](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/faq.html#) * [How to check if my impersonation is working?](https://curl-cffi.readthedocs.io/en/v0.13.0/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/v0.13.0/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/v0.13.0/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/v0.13.0/impersonate/faq.html#can-i-change-javascript-fingerprints-with-this-library) * [Why are all the User-Agents macOS?](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/faq.html#why-are-all-the-user-agents-macos) #### Previous topic [TLS PSK(41) Extension](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/psk.html "previous chapter") #### Next topic [Advanced Topics](https://curl-cffi.readthedocs.io/en/v0.13.0/advanced.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.13.0/_sources/impersonate/faq.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/advanced.html "Advanced Topics") | * [previous](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/psk.html "TLS PSK(41) Extension") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.13.0/index.html) » * [Impersonate Guide](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/_index.html) » * [Impersonation FAQ](https://curl-cffi.readthedocs.io/en/v0.13.0/impersonate/faq.html) --- # FAQ — curl_cffi documentation FAQ[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/faq.html#faq "Link to this heading") ======================================================================================= 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 "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/v0.7.2/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: * [Scrapfly](https://scrapfly.io/?utm_source=github&utm_medium=sponsoring&utm_campaign=curl_cffi) , Cloud-based scraping platform. * [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/v0.7.2/faq.html#i-m-getting-certs-errors "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------- The simplest way is to turn off cert verification by `verify=False`: r \= requests.get("https://example.com", verify\=False) 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 "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Install `curl_cffi` and its dependencies in a pure-ASCII path, i.e. no Chinese or any other characters out of the ASCII table in the path. 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 "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/v0.7.2/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. from curl\_cffi import requests, CurlHttpVersion r \= requests.get("https://postman-echo.com", http\_version\=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/v0.7.2/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 set proxy?[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/faq.html#how-to-set-proxy "Link to this heading") ------------------------------------------------------------------------------------------------------------------ You can use the `proxy` parameter: from curl\_cffi import requests requests.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. For explanation of differences between `http_proxy` and `https_proxy`, please see [#6](https://github.com/lexiforest/curl_cffi/issues/6) . 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 "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? Use `chardet` or `cchardet` \>>> from curl\_cffi import requests \>>> r \= requests.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: [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.2/index.html) ==================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.7.2/vs-requests.html "previous chapter") * Next: [API References](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html "next chapter") --- # FAQ — curl_cffi documentation FAQ[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/faq.html#faq "Link to this heading") ======================================================================================= 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 "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/v0.7.0/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: * [Scrapfly](https://scrapfly.io/?utm_source=github&utm_medium=sponsoring&utm_campaign=curl_cffi) , Cloud-based scraping platform. * [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/v0.7.0/faq.html#i-m-getting-certs-errors "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------- The simplest way is to turn off cert verification by `verify=False`: r \= requests.get("https://example.com", verify\=False) 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 "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Install `curl_cffi` and its dependencies in a pure-ASCII path, i.e. no Chinese or any other characters out of the ASCII table in the path. 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 "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/v0.7.0/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. from curl\_cffi import requests, CurlHttpVersion r \= requests.get("https://postman-echo.com", http\_version\=CurlHttpVersion.V1\_1) Related issues: * [#19](https://github.com/yifeikong/curl_cffi/issues/19) , * [#42](https://github.com/yifeikong/curl_cffi/issues/42) , * [#79](https://github.com/yifeikong/curl_cffi/issues/79) , * [#165](https://github.com/yifeikong/curl_cffi/issues/165) , Packaging with PyInstaller[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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/yifeikong/curl_cffi/issues/5) * [#48](https://github.com/yifeikong/curl_cffi/issues/48) How to set proxy?[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/faq.html#how-to-set-proxy "Link to this heading") ------------------------------------------------------------------------------------------------------------------ You can use the `proxy` parameter: from curl\_cffi import requests requests.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. For explanation of differences between `http_proxy` and `https_proxy`, please see [#6](https://github.com/yifeikong/curl_cffi/issues/6) . 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 "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\=...) [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.0/index.html) ==================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.7.0/vs-requests.html "previous chapter") * Next: [API References](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html "next chapter") ### Quick search --- # FAQ — curl_cffi documentation FAQ[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/faq.html#faq "Link to this heading") ======================================================================================== 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 "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/v0.11.0/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/v0.11.0/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/v0.11.0/faq.html#errcode-77-reason-error-setting-certificate-verify-locations "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Install `curl_cffi` and its dependencies in a pure-ASCII path, i.e. no Chinese or any other characters out of the ASCII table in the path. 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 "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/v0.11.0/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/v0.11.0/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 set proxy?[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/faq.html#how-to-set-proxy "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. For explanation of differences between `http_proxy` and `https_proxy`, please see [#6](https://github.com/lexiforest/curl_cffi/issues/6) . 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 "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? 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: [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.11.0/index.html) ===================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.11.0/vs-requests.html "previous chapter") * Next: [API References](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html "next chapter") --- # FAQ — curl_cffi documentation FAQ[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/faq.html#faq "Link to this heading") ======================================================================================== 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 "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/v0.11.2/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/v0.11.2/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/v0.11.2/faq.html#errcode-77-reason-error-setting-certificate-verify-locations "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Install `curl_cffi` and its dependencies in a pure-ASCII path, i.e. no Chinese or any other characters out of the ASCII table in the path. 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 "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/v0.11.2/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/v0.11.2/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 set proxy?[¶](https://curl-cffi.readthedocs.io/en/v0.11.2/faq.html#how-to-set-proxy "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. For explanation of differences between `http_proxy` and `https_proxy`, please see [#6](https://github.com/lexiforest/curl_cffi/issues/6) . 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 "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? 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: [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.11.2/index.html) ===================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.11.2/vs-requests.html "previous chapter") * Next: [API References](https://curl-cffi.readthedocs.io/en/v0.11.2/api.html "next chapter") --- # FAQ — curl_cffi documentation FAQ[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/faq.html#faq "Link to this heading") ======================================================================================== 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 "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/v0.10.0/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/v0.10.0/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/v0.10.0/faq.html#errcode-77-reason-error-setting-certificate-verify-locations "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Install `curl_cffi` and its dependencies in a pure-ASCII path, i.e. no Chinese or any other characters out of the ASCII table in the path. 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 "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/v0.10.0/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/v0.10.0/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 set proxy?[¶](https://curl-cffi.readthedocs.io/en/v0.10.0/faq.html#how-to-set-proxy "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. For explanation of differences between `http_proxy` and `https_proxy`, please see [#6](https://github.com/lexiforest/curl_cffi/issues/6) . 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 "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? 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: [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.10.0/index.html) ===================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.10.0/vs-requests.html "previous chapter") * Next: [API References](https://curl-cffi.readthedocs.io/en/v0.10.0/api.html "next chapter") --- # Compatibility with requests — curl_cffi documentation Compatibility with requests[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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. Alternatively, 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. [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.11.0/index.html) ===================================================================== ### 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/index.html) * Previous: [Exceptions](https://curl-cffi.readthedocs.io/en/v0.11.0/exceptions.html "previous chapter") * Next: [FAQ](https://curl-cffi.readthedocs.io/en/v0.11.0/faq.html "next chapter") --- # FAQ — curl_cffi documentation FAQ[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/faq.html#faq "Link to this heading") ======================================================================================== 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 "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/v0.11.1/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/v0.11.1/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/v0.11.1/faq.html#errcode-77-reason-error-setting-certificate-verify-locations "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Install `curl_cffi` and its dependencies in a pure-ASCII path, i.e. no Chinese or any other characters out of the ASCII table in the path. 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 "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/v0.11.1/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/v0.11.1/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 set proxy?[¶](https://curl-cffi.readthedocs.io/en/v0.11.1/faq.html#how-to-set-proxy "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. For explanation of differences between `http_proxy` and `https_proxy`, please see [#6](https://github.com/lexiforest/curl_cffi/issues/6) . 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 "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? 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: [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.11.1/index.html) ===================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.11.1/vs-requests.html "previous chapter") * Next: [API References](https://curl-cffi.readthedocs.io/en/v0.11.1/api.html "next chapter") --- # FAQ — curl_cffi documentation FAQ[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/faq.html#faq "Link to this heading") ======================================================================================= 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 "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/v0.7.1/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: * [Scrapfly](https://scrapfly.io/?utm_source=github&utm_medium=sponsoring&utm_campaign=curl_cffi) , Cloud-based scraping platform. * [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/v0.7.1/faq.html#i-m-getting-certs-errors "Link to this heading") --------------------------------------------------------------------------------------------------------------------------------- The simplest way is to turn off cert verification by `verify=False`: r \= requests.get("https://example.com", verify\=False) 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 "Link to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Install `curl_cffi` and its dependencies in a pure-ASCII path, i.e. no Chinese or any other characters out of the ASCII table in the path. 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 "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/v0.7.1/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. from curl\_cffi import requests, CurlHttpVersion r \= requests.get("https://postman-echo.com", http\_version\=CurlHttpVersion.V1\_1) Related issues: * [#19](https://github.com/yifeikong/curl_cffi/issues/19) , * [#42](https://github.com/yifeikong/curl_cffi/issues/42) , * [#79](https://github.com/yifeikong/curl_cffi/issues/79) , * [#165](https://github.com/yifeikong/curl_cffi/issues/165) , Packaging with PyInstaller[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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/yifeikong/curl_cffi/issues/5) * [#48](https://github.com/yifeikong/curl_cffi/issues/48) How to set proxy?[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/faq.html#how-to-set-proxy "Link to this heading") ------------------------------------------------------------------------------------------------------------------ You can use the `proxy` parameter: from curl\_cffi import requests requests.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. For explanation of differences between `http_proxy` and `https_proxy`, please see [#6](https://github.com/yifeikong/curl_cffi/issues/6) . 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 "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? Use `chardet` or `cchardet` \>>> from curl\_cffi import requests \>>> r \= requests.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: [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.1/index.html) ==================================================================== ### 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#) * [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) * [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/index.html) * Previous: [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.7.1/vs-requests.html "previous chapter") * Next: [API References](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html "next chapter") ### Quick search --- # Compatibility with requests — 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/cookies.html "Cookies") | * [previous](https://curl-cffi.readthedocs.io/en/v0.12.0/advanced.html "Advanced Topics") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.12.0/index.html) » * [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.12.0/vs-requests.html) Compatibility with requests[¶](https://curl-cffi.readthedocs.io/en/v0.12.0/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/v0.12.0/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/v0.12.0/index.html) * [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) #### Previous topic [Advanced Topics](https://curl-cffi.readthedocs.io/en/v0.12.0/advanced.html "previous chapter") #### Next topic [Cookies](https://curl-cffi.readthedocs.io/en/v0.12.0/cookies.html "next chapter") ### This Page * [Show Source](https://curl-cffi.readthedocs.io/en/v0.12.0/_sources/vs-requests.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/cookies.html "Cookies") | * [previous](https://curl-cffi.readthedocs.io/en/v0.12.0/advanced.html "Advanced Topics") | * [curl\_cffi documentation](https://curl-cffi.readthedocs.io/en/v0.12.0/index.html) » * [Compatibility with requests](https://curl-cffi.readthedocs.io/en/v0.12.0/vs-requests.html) --- # Index — curl_cffi documentation Index ===== [**\_**](https://curl-cffi.readthedocs.io/en/v0.7.2/genindex.html#_) | [**A**](https://curl-cffi.readthedocs.io/en/v0.7.2/genindex.html#A) | [**C**](https://curl-cffi.readthedocs.io/en/v0.7.2/genindex.html#C) | [**D**](https://curl-cffi.readthedocs.io/en/v0.7.2/genindex.html#D) | [**E**](https://curl-cffi.readthedocs.io/en/v0.7.2/genindex.html#E) | [**F**](https://curl-cffi.readthedocs.io/en/v0.7.2/genindex.html#F) | [**G**](https://curl-cffi.readthedocs.io/en/v0.7.2/genindex.html#G) | [**H**](https://curl-cffi.readthedocs.io/en/v0.7.2/genindex.html#H) | [**I**](https://curl-cffi.readthedocs.io/en/v0.7.2/genindex.html#I) | [**J**](https://curl-cffi.readthedocs.io/en/v0.7.2/genindex.html#J) | [**L**](https://curl-cffi.readthedocs.io/en/v0.7.2/genindex.html#L) | [**M**](https://curl-cffi.readthedocs.io/en/v0.7.2/genindex.html#M) | [**O**](https://curl-cffi.readthedocs.io/en/v0.7.2/genindex.html#O) | [**P**](https://curl-cffi.readthedocs.io/en/v0.7.2/genindex.html#P) | [**R**](https://curl-cffi.readthedocs.io/en/v0.7.2/genindex.html#R) | [**S**](https://curl-cffi.readthedocs.io/en/v0.7.2/genindex.html#S) | [**T**](https://curl-cffi.readthedocs.io/en/v0.7.2/genindex.html#T) | [**U**](https://curl-cffi.readthedocs.io/en/v0.7.2/genindex.html#U) | [**V**](https://curl-cffi.readthedocs.io/en/v0.7.2/genindex.html#V) | [**W**](https://curl-cffi.readthedocs.io/en/v0.7.2/genindex.html#W) \_ -- | | | | --- | --- | | * [\_\_delitem\_\_() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Cookies.__delitem__)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Headers.__delitem__)

* [\_\_getitem\_\_() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Cookies.__getitem__)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Headers.__getitem__)

* [\_\_init\_\_() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.AsyncCurl.__init__)
* [(curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl.__init__)

* [(curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.CurlMime.__init__)

* [(curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.AsyncSession.__init__)

* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Session.__init__)

* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket.__init__) | * [\_\_setitem\_\_() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Cookies.__setitem__)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Headers.__setitem__) | A - | | | | --- | --- | | * [aclose() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.aclose)

* [acontent() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.acontent)

* [add\_handle() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.AsyncCurl.add_handle)

* [addpart() (curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.CurlMime.addpart)

* [aiter\_content() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.aiter_content)

* [aiter\_lines() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.aiter_lines) | * [arecv() (curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket.arecv)

* [asend() (curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket.asend)

* [AsyncCurl (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.AsyncCurl)

* [AsyncSession (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.AsyncSession)

* [atext() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.atext)

* [attach() (curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.CurlMime.attach) | C - | | | | --- | --- | | * [charset (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.charset)

* [charset\_encoding (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.charset_encoding)

* [clear() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Cookies.clear)

* [close() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.AsyncCurl.close)
* [(curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl.close)

* [(curl\_cffi.CurlMime method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.CurlMime.close)

* [(curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.AsyncSession.close)

* [(curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.close)

* [(curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket.close)

* [content (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.content) | * [Cookies (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Cookies)

* [cookies (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.cookies)

* [Curl (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl)

* [CurlECode (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.CurlECode)

* [CurlHttpVersion (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.CurlHttpVersion)

* [CurlInfo (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.CurlInfo)

* [CurlMime (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.CurlMime)

* [CurlMOpt (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.CurlMOpt)

* [CurlOpt (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.CurlOpt)

* [CurlSslVersion (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.CurlSslVersion)

* [CurlWsFlag (class in curl\_cffi)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.CurlWsFlag) | D - | | | | --- | --- | | * [debug() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl.debug)

* [default\_encoding (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.default_encoding) | * [delete() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Cookies.delete)

* [duphandle() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl.duphandle) | E - | | | | --- | --- | | * [elapsed (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.elapsed) | * [encoding (curl\_cffi.requests.Headers property)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Headers.encoding)
* [(curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.encoding) | F - * [from\_list() (curl\_cffi.CurlMime class method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.CurlMime.from_list) G - | | | | --- | --- | | * [get() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Cookies.get)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Headers.get) | * [get\_list() (curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Headers.get_list)

* [get\_reason\_phrase() (curl\_cffi.Curl static method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl.get_reason_phrase)

* [getinfo() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl.getinfo) | H - | | | | --- | --- | | * [Headers (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Headers)

* [headers (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.headers) | * [history (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.history)

* [http\_version (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.http_version) | I - | | | | --- | --- | | * [impersonate() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl.impersonate) | * [iter\_content() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.iter_content)

* [iter\_lines() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.iter_lines) | J - * [json() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.json) L - * [local\_ip (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.local_ip) M - * [multi\_items() (curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Headers.multi_items) O - * [ok (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.ok) P - | | | | --- | --- | | * [parse\_cookie\_headers() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl.parse_cookie_headers)

* [parse\_status\_line() (curl\_cffi.Curl static method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl.parse_status_line) | * [perform() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl.perform)

* [primary\_ip (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.primary_ip)

* [process\_data() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.AsyncCurl.process_data) | R - | | | | --- | --- | | * [raise\_for\_status() (curl\_cffi.requests.Response method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.raise_for_status)

* [raw() (curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Headers.raw)

* [reason (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.reason)

* [recv() (curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket.recv)

* [redirect\_count (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.redirect_count)

* [redirect\_url (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.redirect_url)

* [remove\_handle() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.AsyncCurl.remove_handle) | * [Request (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Request)

* [request() (curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.AsyncSession.request)
* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Session.request)

* [(in module curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.request)

* [reset() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl.reset)

* [Response (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response)

* [run\_forever() (curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket.run_forever) | S - | | | | --- | --- | | * [send() (curl\_cffi.requests.WebSocket method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket.send)

* [Session (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Session)

* [set() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Cookies.set)

* [set\_exception() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.AsyncCurl.set_exception)

* [set\_result() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.AsyncCurl.set_result) | * [setopt() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.AsyncCurl.setopt)
* [(curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl.setopt)

* [socket\_action() (curl\_cffi.AsyncCurl method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.AsyncCurl.socket_action)

* [status\_code (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.status_code)

* [stream() (curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.AsyncSession.stream)
* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Session.stream) | T - * [text (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.text) U - | | | | --- | --- | | * [update() (curl\_cffi.requests.Cookies method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Cookies.update)
* [(curl\_cffi.requests.Headers method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Headers.update) | * [url (curl\_cffi.requests.Response attribute)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.url) | V - * [version() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl.version) W - | | | | --- | --- | | * [WebSocket (class in curl\_cffi.requests)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket)

* [ws\_close() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl.ws_close)

* [ws\_connect() (curl\_cffi.requests.AsyncSession method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.AsyncSession.ws_connect)
* [(curl\_cffi.requests.Session method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Session.ws_connect) | * [ws\_recv() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl.ws_recv)

* [ws\_send() (curl\_cffi.Curl method)](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl.ws_send) | [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.2/index.html) ==================================================================== ### 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/index.html) --- # API References — curl_cffi documentation API References[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#api-references "Link to this heading") ============================================================================================================= curl low levl APIs[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl-low-levl-apis "Link to this heading") --------------------------------------------------------------------------------------------------------------------- ### Curl[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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/v0.7.1/_modules/curl_cffi/curl.html#Curl) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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/v0.7.1/_modules/curl_cffi/curl.html#Curl.__init__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.Curl.__init__ "Link to this definition") Parameters: * **cacert** – CA cert path to use, by default, curl\_cffi uses certs from `certifi`. * **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/v0.7.1/_modules/curl_cffi/curl.html#Curl.debug) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.Curl.debug "Link to this definition") Set debug to True setopt(_option: [CurlOpt](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.CurlOpt "curl_cffi.const.CurlOpt") _, _value: Any_) → int[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/curl.html#Curl.setopt) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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/v0.7.1/api.html#curl_cffi.CurlInfo "curl_cffi.const.CurlInfo") _) → bytes | int | float | List[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/curl.html#Curl.getinfo) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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/v0.7.1/_modules/curl_cffi/curl.html#Curl.version) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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/v0.7.1/_modules/curl_cffi/curl.html#Curl.impersonate) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/curl.html#Curl.perform) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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 Raises: **CurlError** – if the perform was not successful. duphandle() → [Curl](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") [\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/curl.html#Curl.duphandle) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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/v0.7.1/_modules/curl_cffi/curl.html#Curl.reset) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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/v0.7.1/_modules/curl_cffi/curl.html#Curl.parse_cookie_headers) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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/v0.7.1/_modules/curl_cffi/curl.html#Curl.get_reason_phrase) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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/v0.7.1/api.html#curl_cffi.CurlHttpVersion "curl_cffi.const.CurlHttpVersion")\ , int, bytes\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/curl.html#Curl.parse_status_line) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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/v0.7.1/_modules/curl_cffi/curl.html#Curl.close) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.Curl.close "Link to this definition") Close and cleanup curl handle, wrapper for `curl_easy_cleanup`. ws\_recv(_n: int \= 1024_) → Tuple\[bytes, Any\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/curl.html#Curl.ws_recv) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.Curl.ws_recv "Link to this definition") Receive a frame from a websocket connection. Parameters: **n** – maximum data to receive. 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/v0.7.1/api.html#curl_cffi.CurlWsFlag "curl_cffi.const.CurlWsFlag") \= CurlWsFlag.BINARY_) → int[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/curl.html#Curl.ws_send) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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() → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/curl.html#Curl.ws_close) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.Curl.ws_close "Link to this definition") Send the close frame. ### AsyncCurl[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#asynccurl "Link to this heading") _class_ curl\_cffi.AsyncCurl(_cacert: str \= ''_, _loop\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/aio.html#AsyncCurl) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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/v0.7.1/_modules/curl_cffi/aio.html#AsyncCurl.__init__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.AsyncCurl.__init__ "Link to this definition") Parameters: * **cacert** – CA cert path to use, by default, curl\_cffi uses certs from `certifi`. * **loop** – EventLoop to use. add\_handle(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") _)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/aio.html#AsyncCurl.add_handle) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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/v0.7.1/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") _)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/aio.html#AsyncCurl.remove_handle) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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/v0.7.1/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") _)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/aio.html#AsyncCurl.set_result) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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/v0.7.1/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") _, _exception_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/aio.html#AsyncCurl.set_exception) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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/v0.7.1/_modules/curl_cffi/aio.html#AsyncCurl.setopt) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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/v0.7.1/_modules/curl_cffi/aio.html#AsyncCurl.socket_action) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.AsyncCurl.socket_action "Link to this definition") Call libcurl socket\_action function process\_data(_sockfd: int_, _ev\_bitmask: int_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/aio.html#AsyncCurl.process_data) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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/v0.7.1/_modules/curl_cffi/aio.html#AsyncCurl.close) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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/v0.7.1/api.html#curlmime "Link to this heading") _class_ curl\_cffi.CurlMime(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/curl.html#CurlMime) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.CurlMime "Link to this definition") Wrapper for the `curl_mime_` API. \_\_init\_\_(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/curl.html#CurlMime.__init__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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/v0.7.1/_modules/curl_cffi/curl.html#CurlMime.addpart) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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/v0.7.1/_modules/curl_cffi/curl.html#CurlMime.from_list) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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/v0.7.1/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/curl.html#CurlMime.attach) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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/v0.7.1/_modules/curl_cffi/curl.html#CurlMime.close) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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/v0.7.1/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_, _names\=None_, _\*_, _module\=None_, _qualname\=None_, _type\=None_, _start\=1_, _boundary\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/const.html#CurlOpt) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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_, _names\=None_, _\*_, _module\=None_, _qualname\=None_, _type\=None_, _start\=1_, _boundary\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/const.html#CurlInfo) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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_, _names\=None_, _\*_, _module\=None_, _qualname\=None_, _type\=None_, _start\=1_, _boundary\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/const.html#CurlMOpt) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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_, _names\=None_, _\*_, _module\=None_, _qualname\=None_, _type\=None_, _start\=1_, _boundary\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/const.html#CurlECode) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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_, _names\=None_, _\*_, _module\=None_, _qualname\=None_, _type\=None_, _start\=1_, _boundary\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/const.html#CurlHttpVersion) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.CurlHttpVersion "Link to this definition") `CURL_HTTP_VERSION` constants extracted from libcurl, see comments for details. _class_ curl\_cffi.CurlWsFlag(_value_, _names\=None_, _\*_, _module\=None_, _qualname\=None_, _type\=None_, _start\=1_, _boundary\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/const.html#CurlWsFlag) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.CurlWsFlag "Link to this definition") `CURL_WS_FLAG` constants extracted from libcurl, see comments for details. _class_ curl\_cffi.CurlSslVersion(_value_, _names\=None_, _\*_, _module\=None_, _qualname\=None_, _type\=None_, _start\=1_, _boundary\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/const.html#CurlSslVersion) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.CurlSslVersion "Link to this definition") `CURL_SSLVERSION` constants extracted from libcurl, see comments for details. requests API[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#requests-api "Link to this heading") --------------------------------------------------------------------------------------------------------- ### request method[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#request-method "Link to this heading") `requests.get`, `requests.post`, etc are just aliases of `.request(METHOD, ...)` curl\_cffi.requests.request(_method: str_, _url: str_, _params: Dict | List | Tuple | None \= None_, _data: Dict\[str, str\] | List\[Tuple\] | str | BytesIO | bytes | None \= None_, _json: dict | None \= None_, _headers: [Headers](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Headers "curl_cffi.requests.headers.Headers") | Mapping\[str, str | None\] | Mapping\[bytes, bytes | None\] | Sequence\[Tuple\[str, str\]\] | Sequence\[Tuple\[bytes, bytes\]\] | Sequence\[str | bytes\] | None \= None_, _cookies: [Cookies](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Cookies "curl_cffi.requests.cookies.Cookies") | 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\] \= 30_, _allow\_redirects: bool \= True_, _max\_redirects: int \= 30_, _proxies: Dict\[str, str\] | None \= None_, _proxy: str | None \= None_, _proxy\_auth: Tuple\[str, str\] | None \= None_, _verify: bool | None \= None_, _referer: str | None \= None_, _accept\_encoding: str | None \= 'gzip, deflate, br, zstd'_, _content\_callback: Callable | None \= None_, _impersonate: str | BrowserType | None \= None_, _ja3: str | None \= None_, _akamai: str | None \= None_, _extra\_fp: ExtraFingerprints | ExtraFpDict | None \= None_, _thread: Literal\['eventlet', 'gevent'\] | None \= None_, _default\_headers: bool | None \= None_, _default\_encoding: str | Callable\[\[bytes\], str\] \= 'utf-8'_, _curl\_options: dict | None \= None_, _http\_version: [CurlHttpVersion](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.CurlHttpVersion "curl_cffi.const.CurlHttpVersion") | None \= None_, _debug: bool \= False_, _interface: str | None \= None_, _cert: str | Tuple\[str, str\] | None \= None_, _stream: bool \= False_, _max\_recv\_speed: int \= 0_, _multipart: [CurlMime](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.CurlMime "curl_cffi.curl.CurlMime") | None \= None_) → [Response](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response "curl_cffi.requests.models.Response") [\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests.html#request) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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, 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. * **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. Returns: A `Response` object. ### Sessions[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#sessions "Link to this heading") _class_ curl\_cffi.requests.Session(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_, _thread: Literal\['eventlet', 'gevent'\] | None \= None_, _use\_thread\_local\_curl: bool \= True_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/session.html#Session) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/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 seperate session for each thread. \_\_init\_\_(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_, _thread: Literal\['eventlet', 'gevent'\] | None \= None_, _use\_thread\_local\_curl: bool \= True_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/session.html#Session.__init__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Session.__init__ "Link to this definition") Parameters set in the init method will be override 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, 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 strings. * **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. 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: str, url: str, params: ~typing.Dict | ~typing.List | ~typing.Tuple | None \= None, data: ~typing.Dict\[str, str\] | ~typing.List\[~typing.Tuple\] | str | ~\_io.BytesIO | bytes | None \= None, json: dict | None \= None, headers: ~curl\_cffi.requests.headers.Headers | ~collections.abc.Mapping\[str, str | None\] | ~collections.abc.Mapping\[bytes, bytes | None\] | ~collections.abc.Sequence\[~typing.Tuple\[str, str\]\] | ~collections.abc.Sequence\[~typing.Tuple\[bytes, bytes\]\] | ~collections.abc.Sequence\[str | bytes\] | None \= None, cookies: ~curl\_cffi.requests.cookies.Cookies | ~http.cookiejar.CookieJar | ~typing.Dict\[str, str\] | ~typing.List\[~typing.Tuple\[str, str\]\] | None \= None, files: ~typing.Dict | None \= None, auth: ~typing.Tuple\[str, str\] | None \= None, timeout: float | ~typing.Tuple\[float, float\] | object | None \= , allow\_redirects: bool | None \= None, max\_redirects: int | None \= None, proxies: ~typing.Dict\[str, str\] | None \= None, proxy: str | None \= None, proxy\_auth: ~typing.Tuple\[str, str\] | None \= None, verify: bool | None \= None, referer: str | None \= None, accept\_encoding: str | None \= 'gzip, deflate, br', content\_callback: ~typing.Callable | None \= None, impersonate: str | ~curl\_cffi.requests.impersonate.BrowserType | None \= None, ja3: str | None \= None, akamai: str | None \= None, extra\_fp: ~curl\_cffi.requests.impersonate.ExtraFingerprints | ~curl\_cffi.requests.impersonate.ExtraFpDict | None \= None, default\_headers: bool | None \= None, default\_encoding: str | ~typing.Callable\[\[bytes\], str\] \= 'utf-8', http\_version: ~curl\_cffi.const.CurlHttpVersion | None \= None, interface: str | None \= None, cert: str | ~typing.Tuple\[str, str\] | None \= None, stream: bool \= False, max\_recv\_speed: int \= 0, multipart: ~curl\_cffi.curl.CurlMime | None \= None_) → [Response](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response "curl_cffi.requests.models.Response") [\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/session.html#Session.request) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Session.request "Link to this definition") Send the request, see `requests.request` for details on parameters. stream(_\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/session.html#Session.stream) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Session.stream "Link to this definition") Equivalent to `with request(..., stream=True) as r:` ws\_connect(_url_, _\*args_, _on\_message: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ , bytes\], None\] | None \= None_, _on\_error: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ , CurlError\], None\] | None \= None_, _on\_open: Callable | None \= None_, _on\_close: Callable | None \= None_, _\*\*kwargs_) → [WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket") [\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/session.html#Session.ws_connect) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Session.ws_connect "Link to this definition") Connects to a websocket url. Parameters: * **url** – the ws url to connect. * **on\_message** – message callback, `def on_message(ws, str)` * **on\_error** – error callback, `def on_error(ws, error)` * **on\_open** – open callback, `def on_open(ws)` * **on\_close** – close callback, `def on_close(ws)` Other parameters are the same as `.request` Returns: a ws instance to communicate with the server. _class_ curl\_cffi.requests.AsyncSession(_\*_, _loop\=None_, _async\_curl: [AsyncCurl](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.AsyncCurl "curl_cffi.aio.AsyncCurl") | None \= None_, _max\_clients: int \= 10_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/session.html#AsyncSession) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.AsyncSession "Link to this definition") An async request session, cookies and connections will be reused. \_\_init\_\_(_\*_, _loop\=None_, _async\_curl: [AsyncCurl](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.AsyncCurl "curl_cffi.aio.AsyncCurl") | None \= None_, _max\_clients: int \= 10_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/session.html#AsyncSession.__init__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.AsyncSession.__init__ "Link to this definition") Parameters set in the init method will be override by the same parameter in request method. Parameters: * **loop** – loop to use, if not provided, the running loop will be used. * **async\_curl** – \[AsyncCurl\](/api/curl\_cffi#curl\_cffi.AsyncCurl) object to use. * **max\_clients** – maxmium curl handle to use in the session, this will affect the concurrency ratio. * **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, 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 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 strings. * **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. Notes This class can be used as a context manager, and it’s recommended to use via `async with`. However, unlike aiohttp, it is not required to use `with`. from curl\_cffi.requests import AsyncSession \# recommended. async with AsyncSession() as s: r \= await s.get("https://example.com") s \= AsyncSession() \# it also works. _async_ request(_method: str, url: str, params: ~typing.Dict | ~typing.List | ~typing.Tuple | None \= None, data: ~typing.Dict\[str, str\] | ~typing.List\[~typing.Tuple\] | str | ~\_io.BytesIO | bytes | None \= None, json: dict | None \= None, headers: ~curl\_cffi.requests.headers.Headers | ~collections.abc.Mapping\[str, str | None\] | ~collections.abc.Mapping\[bytes, bytes | None\] | ~collections.abc.Sequence\[~typing.Tuple\[str, str\]\] | ~collections.abc.Sequence\[~typing.Tuple\[bytes, bytes\]\] | ~collections.abc.Sequence\[str | bytes\] | None \= None, cookies: ~curl\_cffi.requests.cookies.Cookies | ~http.cookiejar.CookieJar | ~typing.Dict\[str, str\] | ~typing.List\[~typing.Tuple\[str, str\]\] | None \= None, files: ~typing.Dict | None \= None, auth: ~typing.Tuple\[str, str\] | None \= None, timeout: float | ~typing.Tuple\[float, float\] | object | None \= , allow\_redirects: bool | None \= None, max\_redirects: int | None \= None, proxies: ~typing.Dict\[str, str\] | None \= None, proxy: str | None \= None, proxy\_auth: ~typing.Tuple\[str, str\] | None \= None, verify: bool | None \= None, referer: str | None \= None, accept\_encoding: str | None \= 'gzip, deflate, br', content\_callback: ~typing.Callable | None \= None, impersonate: str | ~curl\_cffi.requests.impersonate.BrowserType | None \= None, ja3: str | None \= None, akamai: str | None \= None, extra\_fp: ~curl\_cffi.requests.impersonate.ExtraFingerprints | ~curl\_cffi.requests.impersonate.ExtraFpDict | None \= None, default\_headers: bool | None \= None, default\_encoding: str | ~typing.Callable\[\[bytes\], str\] \= 'utf-8', http\_version: ~curl\_cffi.const.CurlHttpVersion | None \= None, interface: str | None \= None, cert: str | ~typing.Tuple\[str, str\] | None \= None, stream: bool \= False, max\_recv\_speed: int \= 0, multipart: ~curl\_cffi.curl.CurlMime | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/session.html#AsyncSession.request) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.AsyncSession.request "Link to this definition") Send the request, see `curl_cffi.requests.request` for details on parameters. stream(_\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/session.html#AsyncSession.stream) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.AsyncSession.stream "Link to this definition") Equivalent to `async with request(..., stream=True) as r:` _async_ close() → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/session.html#AsyncSession.close) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.AsyncSession.close "Link to this definition") Close the session. _async_ ws\_connect(_url_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/session.html#AsyncSession.ws_connect) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.AsyncSession.ws_connect "Link to this definition") ### Headers[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#headers "Link to this heading") _class_ curl\_cffi.requests.Headers(_headers: [Headers](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Headers "curl_cffi.requests.headers.Headers") | Mapping\[str, str | None\] | Mapping\[bytes, bytes | None\] | Sequence\[Tuple\[str, str\]\] | Sequence\[Tuple\[bytes, bytes\]\] | Sequence\[str | bytes\] | None \= None_, _encoding: str | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/headers.html#Headers) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Headers "Link to this definition") HTTP headers, as a case-insensitive multi-dict. _property_ encoding_: str_[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Headers.encoding "Link to this definition") Header encoding is mandated as ascii, but we allow fallbacks to utf-8 or iso-8859-1. raw()[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Headers.raw "Link to this definition") Returns a list of the raw header items, as byte pairs. multi\_items() → List\[Tuple\[str, str\]\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/headers.html#Headers.multi_items) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Headers.multi_items "Link to this definition") Return a list of (key, value) pairs of headers. Allow multiple occurrences of the same key without concatenating into a single comma separated value. get(_key: str_, _default: Any \= None_) → Any[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/headers.html#Headers.get) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Headers.get "Link to this definition") Return a header value. If multiple occurrences of the header occur then concatenate them together with commas. get\_list(_key: str_, _split\_commas: bool \= False_) → List\[str\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/headers.html#Headers.get_list) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Headers.get_list "Link to this definition") Return a list of all header values for a given key. If split\_commas=True is passed, then any comma separated header values are split into multiple return strings. update(\[_E_, \]_\*\*F_) → None.  Update D from mapping/iterable E and F.[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/headers.html#Headers.update) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Headers.update "Link to this definition") If E present and has a .keys() method, does: for k in E: D\[k\] = E\[k\] If E present and lacks .keys() method, does: for (k, v) in E: D\[k\] = v In either case, this is followed by: for k, v in F.items(): D\[k\] = v \_\_getitem\_\_(_key: str_) → str[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/headers.html#Headers.__getitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Headers.__getitem__ "Link to this definition") Return a single header value. If there are multiple headers with the same key, then we concatenate them with commas. See: [https://tools.ietf.org/html/rfc7230#section-3.2.2](https://tools.ietf.org/html/rfc7230#section-3.2.2) \_\_setitem\_\_(_key: str_, _value: str_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/headers.html#Headers.__setitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Headers.__setitem__ "Link to this definition") Set the header key to value, removing any duplicate entries. Retains insertion order. \_\_delitem\_\_(_key: str_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/headers.html#Headers.__delitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Headers.__delitem__ "Link to this definition") Remove the header key. ### Cookies[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#cookies "Link to this heading") _class_ curl\_cffi.requests.Cookies(_cookies: [Cookies](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Cookies "curl_cffi.requests.cookies.Cookies") | CookieJar | Dict\[str, str\] | List\[Tuple\[str, str\]\] | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/cookies.html#Cookies) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Cookies "Link to this definition") HTTP Cookies, as a mutable mapping. set(_name: str_, _value: str_, _domain: str \= ''_, _path: str \= '/'_, _secure\=False_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/cookies.html#Cookies.set) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Cookies.set "Link to this definition") Set a cookie value by name. May optionally include domain and path. get(_name: str_, _default: str | None \= None_, _domain: str | None \= None_, _path: str | None \= None_) → str | None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/cookies.html#Cookies.get) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Cookies.get "Link to this definition") Get a cookie by name. May optionally include domain and path in order to specify exactly which cookie to retrieve. delete(_name: str_, _domain: str | None \= None_, _path: str | None \= None_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/cookies.html#Cookies.delete) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Cookies.delete "Link to this definition") Delete a cookie by name. May optionally include domain and path in order to specify exactly which cookie to delete. clear(_domain: str | None \= None_, _path: str | None \= None_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/cookies.html#Cookies.clear) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Cookies.clear "Link to this definition") Delete all cookies. Optionally include a domain and path in order to only delete a subset of all the cookies. update(\[_E_, \]_\*\*F_) → None.  Update D from mapping/iterable E and F.[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/cookies.html#Cookies.update) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Cookies.update "Link to this definition") If E present and has a .keys() method, does: for k in E: D\[k\] = E\[k\] If E present and lacks .keys() method, does: for (k, v) in E: D\[k\] = v In either case, this is followed by: for k, v in F.items(): D\[k\] = v \_\_getitem\_\_(_name: str_) → str[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/cookies.html#Cookies.__getitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Cookies.__getitem__ "Link to this definition") \_\_setitem\_\_(_name: str_, _value: str_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/cookies.html#Cookies.__setitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Cookies.__setitem__ "Link to this definition") \_\_delitem\_\_(_name: str_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/cookies.html#Cookies.__delitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Cookies.__delitem__ "Link to this definition") ### Request, Response and WebSocket[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#request-response-and-websocket "Link to this heading") _class_ curl\_cffi.requests.Request(_url: str_, _headers: [Headers](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Headers "curl_cffi.requests.headers.Headers") _, _method: str_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/models.html#Request) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Request "Link to this definition") Representing a sent request. _class_ curl\_cffi.requests.Response(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_, _request: [Request](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Request "curl_cffi.requests.models.Request") | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/models.html#Response) [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response "Link to this definition") Contains information the server sends. url[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.url "Link to this definition") url used in the request. content[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.content "Link to this definition") response body in bytes. text[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.text "Link to this definition") response body in str. status\_code[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.status_code "Link to this definition") http status code. reason[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.reason "Link to this definition") http response reason, such as OK, Not Found. ok[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.ok "Link to this definition") is status\_code in \[200, 400)?\ \ headers[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.headers "Link to this definition")\ \ response headers.\ \ cookies[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.cookies "Link to this definition")\ \ response cookies.\ \ elapsed[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.elapsed "Link to this definition")\ \ how many seconds the request cost.\ \ encoding[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.encoding "Link to this definition")\ \ http body encoding.\ \ charset[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.charset "Link to this definition")\ \ alias for encoding.\ \ primary\_ip[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.primary_ip "Link to this definition")\ \ primary ip of the server.\ \ local\_ip[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.local_ip "Link to this definition")\ \ local ip used in this connection.\ \ charset\_encoding[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.charset_encoding "Link to this definition")\ \ encoding specified by the Content-Type header.\ \ default\_encoding[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.default_encoding "Link to this definition")\ \ 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.\ \ redirect\_count[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.redirect_count "Link to this definition")\ \ how many redirects happened.\ \ redirect\_url[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.redirect_url "Link to this definition")\ \ the final redirected url.\ \ http\_version[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.http_version "Link to this definition")\ \ http version used.\ \ history[¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.history "Link to this definition")\ \ history redirections, only headers are available.\ \ raise\_for\_status()[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/models.html#Response.raise_for_status)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.raise_for_status "Link to this definition")\ \ Raise an error if status code is not in \[200, 400)\ \ iter\_lines(_chunk\_size\=None_, _decode\_unicode\=False_, _delimiter\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/models.html#Response.iter_lines)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.iter_lines "Link to this definition")\ \ iterate streaming content line by line, separated by `\n`.\ \ Copied from: [https://requests.readthedocs.io/en/latest/\_modules/requests/models/](https://requests.readthedocs.io/en/latest/_modules/requests/models/)\ which is under the License: Apache 2.0\ \ iter\_content(_chunk\_size\=None_, _decode\_unicode\=False_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/models.html#Response.iter_content)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.iter_content "Link to this definition")\ \ iterate streaming content chunk by chunk in bytes.\ \ json(_\*\*kw_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/models.html#Response.json)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.json "Link to this definition")\ \ return a parsed json object of the content.\ \ close()[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/models.html#Response.close)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.close "Link to this definition")\ \ Close the streaming connection, only valid in stream mode.\ \ _async_ aiter\_lines(_chunk\_size\=None_, _decode\_unicode\=False_, _delimiter\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/models.html#Response.aiter_lines)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.aiter_lines "Link to this definition")\ \ iterate streaming content line by line, separated by `\n`.\ \ Copied from: [https://requests.readthedocs.io/en/latest/\_modules/requests/models/](https://requests.readthedocs.io/en/latest/_modules/requests/models/)\ which is under the License: Apache 2.0\ \ _async_ aiter\_content(_chunk\_size\=None_, _decode\_unicode\=False_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/models.html#Response.aiter_content)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.aiter_content "Link to this definition")\ \ iterate streaming content chunk by chunk in bytes.\ \ _async_ atext() → str[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/models.html#Response.atext)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.atext "Link to this definition")\ \ Return a decoded string.\ \ _async_ acontent() → bytes[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/models.html#Response.acontent)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.acontent "Link to this definition")\ \ wait and read the streaming content in one bytes object.\ \ _async_ aclose()[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/models.html#Response.aclose)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.Response.aclose "Link to this definition")\ \ Close the streaming connection, only valid in stream mode.\ \ _class_ curl\_cffi.requests.WebSocket(_session_, _curl_, _on\_message: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ , bytes\], None\] | None \= None_, _on\_error: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ , CurlError\], None\] | None \= None_, _on\_open: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ \], None\] | None \= None_, _on\_close: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ , int, str\], None\] | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/websockets.html#WebSocket)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.WebSocket "Link to this definition")\ \ \_\_init\_\_(_session_, _curl_, _on\_message: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ , bytes\], None\] | None \= None_, _on\_error: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ , CurlError\], None\] | None \= None_, _on\_open: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ \], None\] | None \= None_, _on\_close: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ , int, str\], None\] | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/websockets.html#WebSocket.__init__)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.WebSocket.__init__ "Link to this definition")\ \ recv() → Tuple\[bytes, int\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/websockets.html#WebSocket.recv)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.WebSocket.recv "Link to this definition")\ \ Receive a frame as bytes.\ \ libcurl split frames into fragments, so we have to collect all the chunks for a frame.\ \ send(_payload: bytes_, _flags: [CurlWsFlag](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.CurlWsFlag "curl_cffi.const.CurlWsFlag")\ \= CurlWsFlag.BINARY_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/websockets.html#WebSocket.send)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.WebSocket.send "Link to this definition")\ \ Send a data frame\ \ run\_forever()[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/websockets.html#WebSocket.run_forever)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.WebSocket.run_forever "Link to this definition")\ \ libcurl automatically handles pings and pongs.\ \ ref: [https://curl.se/libcurl/c/libcurl-ws.html](https://curl.se/libcurl/c/libcurl-ws.html)\ \ close(_code: int \= WsCloseCode.OK_, _message: bytes \= b''_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/websockets.html#WebSocket.close)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.WebSocket.close "Link to this definition")\ \ _async_ arecv() → Tuple\[bytes, int\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/websockets.html#WebSocket.arecv)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.WebSocket.arecv "Link to this definition")\ \ _async_ asend(_payload: bytes_, _flags: [CurlWsFlag](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.CurlWsFlag "curl_cffi.const.CurlWsFlag")\ \= CurlWsFlag.BINARY_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.1/_modules/curl_cffi/requests/websockets.html#WebSocket.asend)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.1/api.html#curl_cffi.requests.WebSocket.asend "Link to this definition")\ \ [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.1/index.html)\ \ ====================================================================\ \ ### 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#)\ * [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)\ \ \ ### Related Topics\ \ * [Documentation overview](https://curl-cffi.readthedocs.io/en/v0.7.1/index.html)\ * Previous: [FAQ](https://curl-cffi.readthedocs.io/en/v0.7.1/faq.html "previous chapter")\ \ * Next: [Change Log](https://curl-cffi.readthedocs.io/en/v0.7.1/changelog.html "next chapter")\ \ \ ### Quick search --- # API References — curl_cffi documentation API References[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#api-references "Link to this heading") ============================================================================================================= curl low levl APIs[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl-low-levl-apis "Link to this heading") --------------------------------------------------------------------------------------------------------------------- ### Curl[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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/v0.7.2/_modules/curl_cffi/curl.html#Curl) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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/v0.7.2/_modules/curl_cffi/curl.html#Curl.__init__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl.__init__ "Link to this definition") Parameters: * **cacert** – CA cert path to use, by default, curl\_cffi uses certs from `certifi`. * **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/v0.7.2/_modules/curl_cffi/curl.html#Curl.debug) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl.debug "Link to this definition") Set debug to True setopt(_option: [CurlOpt](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.CurlOpt "curl_cffi.const.CurlOpt") _, _value: Any_) → int[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/curl.html#Curl.setopt) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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/v0.7.2/api.html#curl_cffi.CurlInfo "curl_cffi.const.CurlInfo") _) → bytes | int | float | List[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/curl.html#Curl.getinfo) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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/v0.7.2/_modules/curl_cffi/curl.html#Curl.version) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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/v0.7.2/_modules/curl_cffi/curl.html#Curl.impersonate) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/curl.html#Curl.perform) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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 Raises: **CurlError** – if the perform was not successful. duphandle() → [Curl](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") [\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/curl.html#Curl.duphandle) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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/v0.7.2/_modules/curl_cffi/curl.html#Curl.reset) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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/v0.7.2/_modules/curl_cffi/curl.html#Curl.parse_cookie_headers) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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/v0.7.2/_modules/curl_cffi/curl.html#Curl.get_reason_phrase) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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/v0.7.2/api.html#curl_cffi.CurlHttpVersion "curl_cffi.const.CurlHttpVersion")\ , int, bytes\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/curl.html#Curl.parse_status_line) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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/v0.7.2/_modules/curl_cffi/curl.html#Curl.close) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl.close "Link to this definition") Close and cleanup curl handle, wrapper for `curl_easy_cleanup`. ws\_recv(_n: int \= 1024_) → Tuple\[bytes, Any\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/curl.html#Curl.ws_recv) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl.ws_recv "Link to this definition") Receive a frame from a websocket connection. Parameters: **n** – maximum data to receive. 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/v0.7.2/api.html#curl_cffi.CurlWsFlag "curl_cffi.const.CurlWsFlag") \= CurlWsFlag.BINARY_) → int[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/curl.html#Curl.ws_send) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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() → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/curl.html#Curl.ws_close) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl.ws_close "Link to this definition") Send the close frame. ### AsyncCurl[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#asynccurl "Link to this heading") _class_ curl\_cffi.AsyncCurl(_cacert: str \= ''_, _loop\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/aio.html#AsyncCurl) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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/v0.7.2/_modules/curl_cffi/aio.html#AsyncCurl.__init__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.AsyncCurl.__init__ "Link to this definition") Parameters: * **cacert** – CA cert path to use, by default, curl\_cffi uses certs from `certifi`. * **loop** – EventLoop to use. add\_handle(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") _)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/aio.html#AsyncCurl.add_handle) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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/v0.7.2/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") _)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/aio.html#AsyncCurl.remove_handle) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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/v0.7.2/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") _)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/aio.html#AsyncCurl.set_result) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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/v0.7.2/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") _, _exception_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/aio.html#AsyncCurl.set_exception) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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/v0.7.2/_modules/curl_cffi/aio.html#AsyncCurl.setopt) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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/v0.7.2/_modules/curl_cffi/aio.html#AsyncCurl.socket_action) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.AsyncCurl.socket_action "Link to this definition") Call libcurl socket\_action function process\_data(_sockfd: int_, _ev\_bitmask: int_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/aio.html#AsyncCurl.process_data) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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/v0.7.2/_modules/curl_cffi/aio.html#AsyncCurl.close) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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/v0.7.2/api.html#curlmime "Link to this heading") _class_ curl\_cffi.CurlMime(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/curl.html#CurlMime) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.CurlMime "Link to this definition") Wrapper for the `curl_mime_` API. \_\_init\_\_(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/curl.html#CurlMime.__init__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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/v0.7.2/_modules/curl_cffi/curl.html#CurlMime.addpart) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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/v0.7.2/_modules/curl_cffi/curl.html#CurlMime.from_list) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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/v0.7.2/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/curl.html#CurlMime.attach) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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/v0.7.2/_modules/curl_cffi/curl.html#CurlMime.close) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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/v0.7.2/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_, _names\=None_, _\*_, _module\=None_, _qualname\=None_, _type\=None_, _start\=1_, _boundary\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/const.html#CurlOpt) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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_, _names\=None_, _\*_, _module\=None_, _qualname\=None_, _type\=None_, _start\=1_, _boundary\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/const.html#CurlInfo) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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_, _names\=None_, _\*_, _module\=None_, _qualname\=None_, _type\=None_, _start\=1_, _boundary\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/const.html#CurlMOpt) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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_, _names\=None_, _\*_, _module\=None_, _qualname\=None_, _type\=None_, _start\=1_, _boundary\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/const.html#CurlECode) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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_, _names\=None_, _\*_, _module\=None_, _qualname\=None_, _type\=None_, _start\=1_, _boundary\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/const.html#CurlHttpVersion) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.CurlHttpVersion "Link to this definition") `CURL_HTTP_VERSION` constants extracted from libcurl, see comments for details. _class_ curl\_cffi.CurlWsFlag(_value_, _names\=None_, _\*_, _module\=None_, _qualname\=None_, _type\=None_, _start\=1_, _boundary\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/const.html#CurlWsFlag) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.CurlWsFlag "Link to this definition") `CURL_WS_FLAG` constants extracted from libcurl, see comments for details. _class_ curl\_cffi.CurlSslVersion(_value_, _names\=None_, _\*_, _module\=None_, _qualname\=None_, _type\=None_, _start\=1_, _boundary\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/const.html#CurlSslVersion) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.CurlSslVersion "Link to this definition") `CURL_SSLVERSION` constants extracted from libcurl, see comments for details. requests API[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#requests-api "Link to this heading") --------------------------------------------------------------------------------------------------------- ### request method[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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'\]_, _url: str_, _params: Dict | List | Tuple | None \= None_, _data: Dict\[str, str\] | List\[Tuple\] | str | BytesIO | bytes | None \= None_, _json: dict | None \= None_, _headers: [Headers](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Headers "curl_cffi.requests.headers.Headers") | Mapping\[str, str | None\] | Mapping\[bytes, bytes | None\] | Sequence\[Tuple\[str, str\]\] | Sequence\[Tuple\[bytes, bytes\]\] | Sequence\[str | bytes\] | None \= None_, _cookies: [Cookies](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Cookies "curl_cffi.requests.cookies.Cookies") | 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\] \= 30_, _allow\_redirects: bool \= True_, _max\_redirects: int \= 30_, _proxies: Dict\[str, str\] | None \= None_, _proxy: str | None \= None_, _proxy\_auth: Tuple\[str, str\] | None \= None_, _verify: bool | None \= None_, _referer: str | None \= None_, _accept\_encoding: str | None \= 'gzip, deflate, br, zstd'_, _content\_callback: Callable | None \= None_, _impersonate: Literal\['edge99', 'edge101', 'chrome99', 'chrome100', 'chrome101', 'chrome104', 'chrome107', 'chrome110', 'chrome116', 'chrome119', 'chrome120', 'chrome123', 'chrome124', 'chrome99\_android', 'safari15\_3', 'safari15\_5', 'safari17\_0', 'safari17\_2\_ios', 'chrome', 'edge', 'safari', 'safari\_ios', 'chrome\_android'\] | None \= None_, _ja3: str | None \= None_, _akamai: str | None \= None_, _extra\_fp: ExtraFingerprints | ExtraFpDict | None \= None_, _thread: Literal\['eventlet', 'gevent'\] | None \= None_, _default\_headers: bool | None \= None_, _default\_encoding: str | Callable\[\[bytes\], str\] \= 'utf-8'_, _curl\_options: dict | None \= None_, _http\_version: [CurlHttpVersion](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.CurlHttpVersion "curl_cffi.const.CurlHttpVersion") | None \= None_, _debug: bool \= False_, _interface: str | None \= None_, _cert: str | Tuple\[str, str\] | None \= None_, _stream: bool \= False_, _max\_recv\_speed: int \= 0_, _multipart: [CurlMime](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.CurlMime "curl_cffi.curl.CurlMime") | None \= None_) → [Response](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response "curl_cffi.requests.models.Response") [\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests.html#request) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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, 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. * **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. Returns: A `Response` object. ### Sessions[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#sessions "Link to this heading") _class_ curl\_cffi.requests.Session(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_, _thread: Literal\['eventlet', 'gevent'\] | None \= None_, _use\_thread\_local\_curl: bool \= True_, _\*\*kwargs: Unpack_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/session.html#Session) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/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 seperate session for each thread. \_\_init\_\_(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_, _thread: Literal\['eventlet', 'gevent'\] | None \= None_, _use\_thread\_local\_curl: bool \= True_, _\*\*kwargs: Unpack_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/session.html#Session.__init__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Session.__init__ "Link to this definition") Parameters set in the init method will be override 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, 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 strings. * **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. 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'\], url: str, params: ~typing.Dict | ~typing.List | ~typing.Tuple | None \= None, data: ~typing.Dict\[str, str\] | ~typing.List\[~typing.Tuple\] | str | ~\_io.BytesIO | bytes | None \= None, json: dict | None \= None, headers: ~curl\_cffi.requests.headers.Headers | ~collections.abc.Mapping\[str, str | None\] | ~collections.abc.Mapping\[bytes, bytes | None\] | ~collections.abc.Sequence\[~typing.Tuple\[str, str\]\] | ~collections.abc.Sequence\[~typing.Tuple\[bytes, bytes\]\] | ~collections.abc.Sequence\[str | bytes\] | None \= None, cookies: ~curl\_cffi.requests.cookies.Cookies | ~http.cookiejar.CookieJar | ~typing.Dict\[str, str\] | ~typing.List\[~typing.Tuple\[str, str\]\] | None \= None, files: ~typing.Dict | None \= None, auth: ~typing.Tuple\[str, str\] | None \= None, timeout: float | ~typing.Tuple\[float, float\] | object | None \= , allow\_redirects: bool | None \= None, max\_redirects: int | None \= None, proxies: ~typing.Dict\[str, str\] | None \= None, proxy: str | None \= None, proxy\_auth: ~typing.Tuple\[str, str\] | None \= None, verify: bool | None \= None, referer: str | None \= None, accept\_encoding: str | None \= 'gzip, deflate, br', content\_callback: ~typing.Callable | None \= None, impersonate: ~typing.Literal\['edge99', 'edge101', 'chrome99', 'chrome100', 'chrome101', 'chrome104', 'chrome107', 'chrome110', 'chrome116', 'chrome119', 'chrome120', 'chrome123', 'chrome124', 'chrome99\_android', 'safari15\_3', 'safari15\_5', 'safari17\_0', 'safari17\_2\_ios', 'chrome', 'edge', 'safari', 'safari\_ios', 'chrome\_android'\] | None \= None, ja3: str | None \= None, akamai: str | None \= None, extra\_fp: ~curl\_cffi.requests.impersonate.ExtraFingerprints | ~curl\_cffi.requests.impersonate.ExtraFpDict | None \= None, default\_headers: bool | None \= None, default\_encoding: str | ~typing.Callable\[\[bytes\], str\] \= 'utf-8', http\_version: ~curl\_cffi.const.CurlHttpVersion | None \= None, interface: str | None \= None, cert: str | ~typing.Tuple\[str, str\] | None \= None, stream: bool \= False, max\_recv\_speed: int \= 0, multipart: ~curl\_cffi.curl.CurlMime | None \= None_) → [Response](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response "curl_cffi.requests.models.Response") [\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/session.html#Session.request) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Session.request "Link to this definition") Send the request, see `requests.request` for details on parameters. stream(_\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/session.html#Session.stream) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Session.stream "Link to this definition") Equivalent to `with request(..., stream=True) as r:` ws\_connect(_url_, _\*args_, _on\_message: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ , bytes\], None\] | None \= None_, _on\_error: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ , CurlError\], None\] | None \= None_, _on\_open: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ \], None\] | None \= None_, _on\_close: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ , int, str\], None\] | None \= None_, _\*\*kwargs_) → [WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket") [\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/session.html#Session.ws_connect) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Session.ws_connect "Link to this definition") Connects to a websocket url. Parameters: * **url** – the ws url to connect. * **on\_message** – message callback, `def on_message(ws, str)` * **on\_error** – error callback, `def on_error(ws, error)` * **on\_open** – open callback, `def on_open(ws)` * **on\_close** – close callback, `def on_close(ws)` Other parameters are the same as `.request` Returns: a ws instance to communicate with the server. _class_ curl\_cffi.requests.AsyncSession(_\*_, _loop\=None_, _async\_curl: [AsyncCurl](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.AsyncCurl "curl_cffi.aio.AsyncCurl") | None \= None_, _max\_clients: int \= 10_, _\*\*kwargs: Unpack_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/session.html#AsyncSession) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.AsyncSession "Link to this definition") An async request session, cookies and connections will be reused. \_\_init\_\_(_\*_, _loop\=None_, _async\_curl: [AsyncCurl](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.AsyncCurl "curl_cffi.aio.AsyncCurl") | None \= None_, _max\_clients: int \= 10_, _\*\*kwargs: Unpack_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/session.html#AsyncSession.__init__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.AsyncSession.__init__ "Link to this definition") Parameters set in the init method will be override by the same parameter in request method. Parameters: * **loop** – loop to use, if not provided, the running loop will be used. * **async\_curl** – \[AsyncCurl\](/api/curl\_cffi#curl\_cffi.AsyncCurl) object to use. * **max\_clients** – maxmium curl handle to use in the session, this will affect the concurrency ratio. * **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, 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 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 strings. * **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. Notes This class can be used as a context manager, and it’s recommended to use via `async with`. However, unlike aiohttp, it is not required to use `with`. from curl\_cffi.requests import AsyncSession \# recommended. async with AsyncSession() as s: r \= await s.get("https://example.com") s \= AsyncSession() \# it also works. _async_ request(_method: ~typing.Literal\['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD', 'TRACE', 'PATCH'\], url: str, params: ~typing.Dict | ~typing.List | ~typing.Tuple | None \= None, data: ~typing.Dict\[str, str\] | ~typing.List\[~typing.Tuple\] | str | ~\_io.BytesIO | bytes | None \= None, json: dict | None \= None, headers: ~curl\_cffi.requests.headers.Headers | ~collections.abc.Mapping\[str, str | None\] | ~collections.abc.Mapping\[bytes, bytes | None\] | ~collections.abc.Sequence\[~typing.Tuple\[str, str\]\] | ~collections.abc.Sequence\[~typing.Tuple\[bytes, bytes\]\] | ~collections.abc.Sequence\[str | bytes\] | None \= None, cookies: ~curl\_cffi.requests.cookies.Cookies | ~http.cookiejar.CookieJar | ~typing.Dict\[str, str\] | ~typing.List\[~typing.Tuple\[str, str\]\] | None \= None, files: ~typing.Dict | None \= None, auth: ~typing.Tuple\[str, str\] | None \= None, timeout: float | ~typing.Tuple\[float, float\] | object | None \= , allow\_redirects: bool | None \= None, max\_redirects: int | None \= None, proxies: ~typing.Dict\[str, str\] | None \= None, proxy: str | None \= None, proxy\_auth: ~typing.Tuple\[str, str\] | None \= None, verify: bool | None \= None, referer: str | None \= None, accept\_encoding: str | None \= 'gzip, deflate, br', content\_callback: ~typing.Callable | None \= None, impersonate: ~typing.Literal\['edge99', 'edge101', 'chrome99', 'chrome100', 'chrome101', 'chrome104', 'chrome107', 'chrome110', 'chrome116', 'chrome119', 'chrome120', 'chrome123', 'chrome124', 'chrome99\_android', 'safari15\_3', 'safari15\_5', 'safari17\_0', 'safari17\_2\_ios', 'chrome', 'edge', 'safari', 'safari\_ios', 'chrome\_android'\] | None \= None, ja3: str | None \= None, akamai: str | None \= None, extra\_fp: ~curl\_cffi.requests.impersonate.ExtraFingerprints | ~curl\_cffi.requests.impersonate.ExtraFpDict | None \= None, default\_headers: bool | None \= None, default\_encoding: str | ~typing.Callable\[\[bytes\], str\] \= 'utf-8', http\_version: ~curl\_cffi.const.CurlHttpVersion | None \= None, interface: str | None \= None, cert: str | ~typing.Tuple\[str, str\] | None \= None, stream: bool \= False, max\_recv\_speed: int \= 0, multipart: ~curl\_cffi.curl.CurlMime | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/session.html#AsyncSession.request) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.AsyncSession.request "Link to this definition") Send the request, see `curl_cffi.requests.request` for details on parameters. stream(_\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/session.html#AsyncSession.stream) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.AsyncSession.stream "Link to this definition") Equivalent to `async with request(..., stream=True) as r:` _async_ close() → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/session.html#AsyncSession.close) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.AsyncSession.close "Link to this definition") Close the session. _async_ ws\_connect(_url_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/session.html#AsyncSession.ws_connect) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.AsyncSession.ws_connect "Link to this definition") ### Headers[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#headers "Link to this heading") _class_ curl\_cffi.requests.Headers(_headers: [Headers](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Headers "curl_cffi.requests.headers.Headers") | Mapping\[str, str | None\] | Mapping\[bytes, bytes | None\] | Sequence\[Tuple\[str, str\]\] | Sequence\[Tuple\[bytes, bytes\]\] | Sequence\[str | bytes\] | None \= None_, _encoding: str | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/headers.html#Headers) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Headers "Link to this definition") HTTP headers, as a case-insensitive multi-dict. _property_ encoding_: str_[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Headers.encoding "Link to this definition") Header encoding is mandated as ascii, but we allow fallbacks to utf-8 or iso-8859-1. raw()[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Headers.raw "Link to this definition") Returns a list of the raw header items, as byte pairs. multi\_items() → List\[Tuple\[str, str\]\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/headers.html#Headers.multi_items) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Headers.multi_items "Link to this definition") Return a list of (key, value) pairs of headers. Allow multiple occurrences of the same key without concatenating into a single comma separated value. get(_key: str_, _default: Any \= None_) → Any[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/headers.html#Headers.get) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Headers.get "Link to this definition") Return a header value. If multiple occurrences of the header occur then concatenate them together with commas. get\_list(_key: str_, _split\_commas: bool \= False_) → List\[str\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/headers.html#Headers.get_list) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Headers.get_list "Link to this definition") Return a list of all header values for a given key. If split\_commas=True is passed, then any comma separated header values are split into multiple return strings. update(\[_E_, \]_\*\*F_) → None.  Update D from mapping/iterable E and F.[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/headers.html#Headers.update) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Headers.update "Link to this definition") If E present and has a .keys() method, does: for k in E: D\[k\] = E\[k\] If E present and lacks .keys() method, does: for (k, v) in E: D\[k\] = v In either case, this is followed by: for k, v in F.items(): D\[k\] = v \_\_getitem\_\_(_key: str_) → str[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/headers.html#Headers.__getitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Headers.__getitem__ "Link to this definition") Return a single header value. If there are multiple headers with the same key, then we concatenate them with commas. See: [https://tools.ietf.org/html/rfc7230#section-3.2.2](https://tools.ietf.org/html/rfc7230#section-3.2.2) \_\_setitem\_\_(_key: str_, _value: str_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/headers.html#Headers.__setitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Headers.__setitem__ "Link to this definition") Set the header key to value, removing any duplicate entries. Retains insertion order. \_\_delitem\_\_(_key: str_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/headers.html#Headers.__delitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Headers.__delitem__ "Link to this definition") Remove the header key. ### Cookies[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#cookies "Link to this heading") _class_ curl\_cffi.requests.Cookies(_cookies: [Cookies](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Cookies "curl_cffi.requests.cookies.Cookies") | CookieJar | Dict\[str, str\] | List\[Tuple\[str, str\]\] | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/cookies.html#Cookies) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Cookies "Link to this definition") HTTP Cookies, as a mutable mapping. set(_name: str_, _value: str_, _domain: str \= ''_, _path: str \= '/'_, _secure\=False_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/cookies.html#Cookies.set) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Cookies.set "Link to this definition") Set a cookie value by name. May optionally include domain and path. get(_name: str_, _default: str | None \= None_, _domain: str | None \= None_, _path: str | None \= None_) → str | None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/cookies.html#Cookies.get) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Cookies.get "Link to this definition") Get a cookie by name. May optionally include domain and path in order to specify exactly which cookie to retrieve. delete(_name: str_, _domain: str | None \= None_, _path: str | None \= None_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/cookies.html#Cookies.delete) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Cookies.delete "Link to this definition") Delete a cookie by name. May optionally include domain and path in order to specify exactly which cookie to delete. clear(_domain: str | None \= None_, _path: str | None \= None_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/cookies.html#Cookies.clear) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Cookies.clear "Link to this definition") Delete all cookies. Optionally include a domain and path in order to only delete a subset of all the cookies. update(\[_E_, \]_\*\*F_) → None.  Update D from mapping/iterable E and F.[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/cookies.html#Cookies.update) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Cookies.update "Link to this definition") If E present and has a .keys() method, does: for k in E: D\[k\] = E\[k\] If E present and lacks .keys() method, does: for (k, v) in E: D\[k\] = v In either case, this is followed by: for k, v in F.items(): D\[k\] = v \_\_getitem\_\_(_name: str_) → str[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/cookies.html#Cookies.__getitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Cookies.__getitem__ "Link to this definition") \_\_setitem\_\_(_name: str_, _value: str_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/cookies.html#Cookies.__setitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Cookies.__setitem__ "Link to this definition") \_\_delitem\_\_(_name: str_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/cookies.html#Cookies.__delitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Cookies.__delitem__ "Link to this definition") ### Request, Response and WebSocket[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#request-response-and-websocket "Link to this heading") _class_ curl\_cffi.requests.Request(_url: str_, _headers: [Headers](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Headers "curl_cffi.requests.headers.Headers") _, _method: str_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/models.html#Request) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Request "Link to this definition") Representing a sent request. _class_ curl\_cffi.requests.Response(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_, _request: [Request](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Request "curl_cffi.requests.models.Request") | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/models.html#Response) [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response "Link to this definition") Contains information the server sends. url[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.url "Link to this definition") url used in the request. content[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.content "Link to this definition") response body in bytes. text[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.text "Link to this definition") response body in str. status\_code[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.status_code "Link to this definition") http status code. reason[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.reason "Link to this definition") http response reason, such as OK, Not Found. ok[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.ok "Link to this definition") is status\_code in \[200, 400)?\ \ headers[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.headers "Link to this definition")\ \ response headers.\ \ cookies[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.cookies "Link to this definition")\ \ response cookies.\ \ elapsed[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.elapsed "Link to this definition")\ \ how many seconds the request cost.\ \ encoding[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.encoding "Link to this definition")\ \ http body encoding.\ \ charset[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.charset "Link to this definition")\ \ alias for encoding.\ \ primary\_ip[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.primary_ip "Link to this definition")\ \ primary ip of the server.\ \ local\_ip[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.local_ip "Link to this definition")\ \ local ip used in this connection.\ \ charset\_encoding[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.charset_encoding "Link to this definition")\ \ encoding specified by the Content-Type header.\ \ default\_encoding[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.default_encoding "Link to this definition")\ \ 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.\ \ redirect\_count[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.redirect_count "Link to this definition")\ \ how many redirects happened.\ \ redirect\_url[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.redirect_url "Link to this definition")\ \ the final redirected url.\ \ http\_version[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.http_version "Link to this definition")\ \ http version used.\ \ history[¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.history "Link to this definition")\ \ history redirections, only headers are available.\ \ raise\_for\_status()[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/models.html#Response.raise_for_status)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.raise_for_status "Link to this definition")\ \ Raise an error if status code is not in \[200, 400)\ \ iter\_lines(_chunk\_size\=None_, _decode\_unicode\=False_, _delimiter\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/models.html#Response.iter_lines)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.iter_lines "Link to this definition")\ \ iterate streaming content line by line, separated by `\n`.\ \ Copied from: [https://requests.readthedocs.io/en/latest/\_modules/requests/models/](https://requests.readthedocs.io/en/latest/_modules/requests/models/)\ which is under the License: Apache 2.0\ \ iter\_content(_chunk\_size\=None_, _decode\_unicode\=False_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/models.html#Response.iter_content)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.iter_content "Link to this definition")\ \ iterate streaming content chunk by chunk in bytes.\ \ json(_\*\*kw_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/models.html#Response.json)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.json "Link to this definition")\ \ return a parsed json object of the content.\ \ close()[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/models.html#Response.close)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.close "Link to this definition")\ \ Close the streaming connection, only valid in stream mode.\ \ _async_ aiter\_lines(_chunk\_size\=None_, _decode\_unicode\=False_, _delimiter\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/models.html#Response.aiter_lines)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.aiter_lines "Link to this definition")\ \ iterate streaming content line by line, separated by `\n`.\ \ Copied from: [https://requests.readthedocs.io/en/latest/\_modules/requests/models/](https://requests.readthedocs.io/en/latest/_modules/requests/models/)\ which is under the License: Apache 2.0\ \ _async_ aiter\_content(_chunk\_size\=None_, _decode\_unicode\=False_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/models.html#Response.aiter_content)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.aiter_content "Link to this definition")\ \ iterate streaming content chunk by chunk in bytes.\ \ _async_ atext() → str[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/models.html#Response.atext)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.atext "Link to this definition")\ \ Return a decoded string.\ \ _async_ acontent() → bytes[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/models.html#Response.acontent)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.acontent "Link to this definition")\ \ wait and read the streaming content in one bytes object.\ \ _async_ aclose()[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/models.html#Response.aclose)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.Response.aclose "Link to this definition")\ \ Close the streaming connection, only valid in stream mode.\ \ _class_ curl\_cffi.requests.WebSocket(_session_, _curl_, _on\_message: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ , bytes\], None\] | None \= None_, _on\_error: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ , CurlError\], None\] | None \= None_, _on\_open: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ \], None\] | None \= None_, _on\_close: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ , int, str\], None\] | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/websockets.html#WebSocket)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket "Link to this definition")\ \ \_\_init\_\_(_session_, _curl_, _on\_message: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ , bytes\], None\] | None \= None_, _on\_error: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ , CurlError\], None\] | None \= None_, _on\_open: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ \], None\] | None \= None_, _on\_close: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ , int, str\], None\] | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/websockets.html#WebSocket.__init__)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket.__init__ "Link to this definition")\ \ recv() → Tuple\[bytes, int\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/websockets.html#WebSocket.recv)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket.recv "Link to this definition")\ \ Receive a frame as bytes.\ \ libcurl split frames into fragments, so we have to collect all the chunks for a frame.\ \ send(_payload: bytes_, _flags: [CurlWsFlag](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.CurlWsFlag "curl_cffi.const.CurlWsFlag")\ \= CurlWsFlag.BINARY_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/websockets.html#WebSocket.send)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket.send "Link to this definition")\ \ Send a data frame\ \ run\_forever()[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/websockets.html#WebSocket.run_forever)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket.run_forever "Link to this definition")\ \ libcurl automatically handles pings and pongs.\ \ ref: [https://curl.se/libcurl/c/libcurl-ws.html](https://curl.se/libcurl/c/libcurl-ws.html)\ \ close(_code: int \= WsCloseCode.OK_, _message: bytes \= b''_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/websockets.html#WebSocket.close)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket.close "Link to this definition")\ \ _async_ arecv() → Tuple\[bytes, int\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/websockets.html#WebSocket.arecv)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket.arecv "Link to this definition")\ \ _async_ asend(_payload: bytes_, _flags: [CurlWsFlag](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.CurlWsFlag "curl_cffi.const.CurlWsFlag")\ \= CurlWsFlag.BINARY_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.2/_modules/curl_cffi/requests/websockets.html#WebSocket.asend)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.2/api.html#curl_cffi.requests.WebSocket.asend "Link to this definition")\ \ [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.2/index.html)\ \ ====================================================================\ \ \ \ ### 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#)\ * [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)\ \ \ ### Related Topics\ \ * [Documentation overview](https://curl-cffi.readthedocs.io/en/v0.7.2/index.html)\ * Previous: [FAQ](https://curl-cffi.readthedocs.io/en/v0.7.2/faq.html "previous chapter")\ \ * Next: [Change Log](https://curl-cffi.readthedocs.io/en/v0.7.2/changelog.html "next chapter") --- # API References — curl_cffi documentation API References[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#api-references "Link to this heading") ============================================================================================================= curl low levl APIs[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl-low-levl-apis "Link to this heading") --------------------------------------------------------------------------------------------------------------------- ### Curl[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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/v0.7.0/_modules/curl_cffi/curl.html#Curl) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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/v0.7.0/_modules/curl_cffi/curl.html#Curl.__init__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.Curl.__init__ "Link to this definition") Parameters: * **cacert** – CA cert path to use, by default, curl\_cffi uses certs from `certifi`. * **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/v0.7.0/_modules/curl_cffi/curl.html#Curl.debug) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.Curl.debug "Link to this definition") Set debug to True setopt(_option: [CurlOpt](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.CurlOpt "curl_cffi.const.CurlOpt") _, _value: Any_) → int[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/curl.html#Curl.setopt) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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/v0.7.0/api.html#curl_cffi.CurlInfo "curl_cffi.const.CurlInfo") _) → bytes | int | float | List[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/curl.html#Curl.getinfo) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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/v0.7.0/_modules/curl_cffi/curl.html#Curl.version) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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/v0.7.0/_modules/curl_cffi/curl.html#Curl.impersonate) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/curl.html#Curl.perform) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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 Raises: **CurlError** – if the perform was not successful. duphandle() → [Curl](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") [\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/curl.html#Curl.duphandle) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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/v0.7.0/_modules/curl_cffi/curl.html#Curl.reset) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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/v0.7.0/_modules/curl_cffi/curl.html#Curl.parse_cookie_headers) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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/v0.7.0/_modules/curl_cffi/curl.html#Curl.get_reason_phrase) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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/v0.7.0/api.html#curl_cffi.CurlHttpVersion "curl_cffi.const.CurlHttpVersion")\ , int, bytes\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/curl.html#Curl.parse_status_line) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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/v0.7.0/_modules/curl_cffi/curl.html#Curl.close) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.Curl.close "Link to this definition") Close and cleanup curl handle, wrapper for `curl_easy_cleanup`. ws\_recv(_n: int \= 1024_) → Tuple\[bytes, Any\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/curl.html#Curl.ws_recv) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.Curl.ws_recv "Link to this definition") Receive a frame from a websocket connection. Parameters: **n** – maximum data to receive. 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/v0.7.0/api.html#curl_cffi.CurlWsFlag "curl_cffi.const.CurlWsFlag") \= CurlWsFlag.BINARY_) → int[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/curl.html#Curl.ws_send) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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() → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/curl.html#Curl.ws_close) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.Curl.ws_close "Link to this definition") Send the close frame. ### AsyncCurl[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#asynccurl "Link to this heading") _class_ curl\_cffi.AsyncCurl(_cacert: str \= ''_, _loop\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/aio.html#AsyncCurl) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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/v0.7.0/_modules/curl_cffi/aio.html#AsyncCurl.__init__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.AsyncCurl.__init__ "Link to this definition") Parameters: * **cacert** – CA cert path to use, by default, curl\_cffi uses certs from `certifi`. * **loop** – EventLoop to use. add\_handle(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") _)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/aio.html#AsyncCurl.add_handle) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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/v0.7.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") _)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/aio.html#AsyncCurl.remove_handle) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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/v0.7.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") _)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/aio.html#AsyncCurl.set_result) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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/v0.7.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") _, _exception_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/aio.html#AsyncCurl.set_exception) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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/v0.7.0/_modules/curl_cffi/aio.html#AsyncCurl.setopt) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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/v0.7.0/_modules/curl_cffi/aio.html#AsyncCurl.socket_action) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.AsyncCurl.socket_action "Link to this definition") Call libcurl socket\_action function process\_data(_sockfd: int_, _ev\_bitmask: int_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/aio.html#AsyncCurl.process_data) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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/v0.7.0/_modules/curl_cffi/aio.html#AsyncCurl.close) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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/v0.7.0/api.html#curlmime "Link to this heading") _class_ curl\_cffi.CurlMime(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/curl.html#CurlMime) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.CurlMime "Link to this definition") Wrapper for the `curl_mime_` API. \_\_init\_\_(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/curl.html#CurlMime.__init__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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/v0.7.0/_modules/curl_cffi/curl.html#CurlMime.addpart) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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/v0.7.0/_modules/curl_cffi/curl.html#CurlMime.from_list) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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/v0.7.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/curl.html#CurlMime.attach) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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/v0.7.0/_modules/curl_cffi/curl.html#CurlMime.close) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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/v0.7.0/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_, _names\=None_, _\*_, _module\=None_, _qualname\=None_, _type\=None_, _start\=1_, _boundary\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/const.html#CurlOpt) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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_, _names\=None_, _\*_, _module\=None_, _qualname\=None_, _type\=None_, _start\=1_, _boundary\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/const.html#CurlInfo) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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_, _names\=None_, _\*_, _module\=None_, _qualname\=None_, _type\=None_, _start\=1_, _boundary\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/const.html#CurlMOpt) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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_, _names\=None_, _\*_, _module\=None_, _qualname\=None_, _type\=None_, _start\=1_, _boundary\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/const.html#CurlECode) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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_, _names\=None_, _\*_, _module\=None_, _qualname\=None_, _type\=None_, _start\=1_, _boundary\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/const.html#CurlHttpVersion) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.CurlHttpVersion "Link to this definition") `CURL_HTTP_VERSION` constants extracted from libcurl, see comments for details. _class_ curl\_cffi.CurlWsFlag(_value_, _names\=None_, _\*_, _module\=None_, _qualname\=None_, _type\=None_, _start\=1_, _boundary\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/const.html#CurlWsFlag) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.CurlWsFlag "Link to this definition") `CURL_WS_FLAG` constants extracted from libcurl, see comments for details. _class_ curl\_cffi.CurlSslVersion(_value_, _names\=None_, _\*_, _module\=None_, _qualname\=None_, _type\=None_, _start\=1_, _boundary\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/const.html#CurlSslVersion) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.CurlSslVersion "Link to this definition") `CURL_SSLVERSION` constants extracted from libcurl, see comments for details. requests API[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#requests-api "Link to this heading") --------------------------------------------------------------------------------------------------------- ### request method[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#request-method "Link to this heading") `requests.get`, `requests.post`, etc are just aliases of `.request(METHOD, ...)` curl\_cffi.requests.request(_method: str_, _url: str_, _params: Dict | List | Tuple | None \= None_, _data: Dict\[str, str\] | List\[Tuple\] | str | BytesIO | bytes | None \= None_, _json: dict | None \= None_, _headers: [Headers](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Headers "curl_cffi.requests.headers.Headers") | Mapping\[str, str | None\] | Mapping\[bytes, bytes | None\] | Sequence\[Tuple\[str, str\]\] | Sequence\[Tuple\[bytes, bytes\]\] | Sequence\[str | bytes\] | None \= None_, _cookies: [Cookies](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Cookies "curl_cffi.requests.cookies.Cookies") | 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\] \= 30_, _allow\_redirects: bool \= True_, _max\_redirects: int \= 30_, _proxies: Dict\[str, str\] | None \= None_, _proxy: str | None \= None_, _proxy\_auth: Tuple\[str, str\] | None \= None_, _verify: bool | None \= None_, _referer: str | None \= None_, _accept\_encoding: str | None \= 'gzip, deflate, br, zstd'_, _content\_callback: Callable | None \= None_, _impersonate: str | BrowserType | None \= None_, _ja3: str | None \= None_, _akamai: str | None \= None_, _extra\_fp: ExtraFingerprints | ExtraFpDict | None \= None_, _thread: Literal\['eventlet', 'gevent'\] | None \= None_, _default\_headers: bool | None \= None_, _default\_encoding: str | Callable\[\[bytes\], str\] \= 'utf-8'_, _curl\_options: dict | None \= None_, _http\_version: [CurlHttpVersion](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.CurlHttpVersion "curl_cffi.const.CurlHttpVersion") | None \= None_, _debug: bool \= False_, _interface: str | None \= None_, _cert: str | Tuple\[str, str\] | None \= None_, _stream: bool \= False_, _max\_recv\_speed: int \= 0_, _multipart: [CurlMime](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.CurlMime "curl_cffi.curl.CurlMime") | None \= None_) → [Response](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response "curl_cffi.requests.models.Response") [\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests.html#request) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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, 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. * **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. Returns: A `Response` object. ### Sessions[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#sessions "Link to this heading") _class_ curl\_cffi.requests.Session(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_, _thread: Literal\['eventlet', 'gevent'\] | None \= None_, _use\_thread\_local\_curl: bool \= True_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/session.html#Session) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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 seperate session for each thread. \_\_init\_\_(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_, _thread: Literal\['eventlet', 'gevent'\] | None \= None_, _use\_thread\_local\_curl: bool \= True_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/session.html#Session.__init__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Session.__init__ "Link to this definition") Parameters set in the init method will be override 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, 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 strings. * **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. 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: str, url: str, params: ~typing.Dict | ~typing.List | ~typing.Tuple | None \= None, data: ~typing.Dict\[str, str\] | ~typing.List\[~typing.Tuple\] | str | ~\_io.BytesIO | bytes | None \= None, json: dict | None \= None, headers: ~curl\_cffi.requests.headers.Headers | ~collections.abc.Mapping\[str, str | None\] | ~collections.abc.Mapping\[bytes, bytes | None\] | ~collections.abc.Sequence\[~typing.Tuple\[str, str\]\] | ~collections.abc.Sequence\[~typing.Tuple\[bytes, bytes\]\] | ~collections.abc.Sequence\[str | bytes\] | None \= None, cookies: ~curl\_cffi.requests.cookies.Cookies | ~http.cookiejar.CookieJar | ~typing.Dict\[str, str\] | ~typing.List\[~typing.Tuple\[str, str\]\] | None \= None, files: ~typing.Dict | None \= None, auth: ~typing.Tuple\[str, str\] | None \= None, timeout: float | ~typing.Tuple\[float, float\] | object | None \= , allow\_redirects: bool | None \= None, max\_redirects: int | None \= None, proxies: ~typing.Dict\[str, str\] | None \= None, proxy: str | None \= None, proxy\_auth: ~typing.Tuple\[str, str\] | None \= None, verify: bool | None \= None, referer: str | None \= None, accept\_encoding: str | None \= 'gzip, deflate, br', content\_callback: ~typing.Callable | None \= None, impersonate: str | ~curl\_cffi.requests.impersonate.BrowserType | None \= None, ja3: str | None \= None, akamai: str | None \= None, extra\_fp: ~curl\_cffi.requests.impersonate.ExtraFingerprints | ~curl\_cffi.requests.impersonate.ExtraFpDict | None \= None, default\_headers: bool | None \= None, default\_encoding: str | ~typing.Callable\[\[bytes\], str\] \= 'utf-8', http\_version: ~curl\_cffi.const.CurlHttpVersion | None \= None, interface: str | None \= None, cert: str | ~typing.Tuple\[str, str\] | None \= None, stream: bool \= False, max\_recv\_speed: int \= 0, multipart: ~curl\_cffi.curl.CurlMime | None \= None_) → [Response](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response "curl_cffi.requests.models.Response") [\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/session.html#Session.request) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Session.request "Link to this definition") Send the request, see `requests.request` for details on parameters. stream(_\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/session.html#Session.stream) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Session.stream "Link to this definition") Equivalent to `with request(..., stream=True) as r:` ws\_connect(_url_, _\*args_, _on\_message: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ , bytes\], None\] | None \= None_, _on\_error: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ , CurlError\], None\] | None \= None_, _on\_open: Callable | None \= None_, _on\_close: Callable | None \= None_, _\*\*kwargs_) → [WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket") [\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/session.html#Session.ws_connect) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Session.ws_connect "Link to this definition") Connects to a websocket url. Parameters: * **url** – the ws url to connect. * **on\_message** – message callback, `def on_message(ws, str)` * **on\_error** – error callback, `def on_error(ws, error)` * **on\_open** – open callback, `def on_open(ws)` * **on\_close** – close callback, `def on_close(ws)` Other parameters are the same as `.request` Returns: a ws instance to communicate with the server. _class_ curl\_cffi.requests.AsyncSession(_\*_, _loop\=None_, _async\_curl: [AsyncCurl](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.AsyncCurl "curl_cffi.aio.AsyncCurl") | None \= None_, _max\_clients: int \= 10_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/session.html#AsyncSession) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.AsyncSession "Link to this definition") An async request session, cookies and connections will be reused. \_\_init\_\_(_\*_, _loop\=None_, _async\_curl: [AsyncCurl](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.AsyncCurl "curl_cffi.aio.AsyncCurl") | None \= None_, _max\_clients: int \= 10_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/session.html#AsyncSession.__init__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.AsyncSession.__init__ "Link to this definition") Parameters set in the init method will be override by the same parameter in request method. Parameters: * **loop** – loop to use, if not provided, the running loop will be used. * **async\_curl** – \[AsyncCurl\](/api/curl\_cffi#curl\_cffi.AsyncCurl) object to use. * **max\_clients** – maxmium curl handle to use in the session, this will affect the concurrency ratio. * **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, 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 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 strings. * **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. Notes This class can be used as a context manager, and it’s recommended to use via `async with`. However, unlike aiohttp, it is not required to use `with`. from curl\_cffi.requests import AsyncSession \# recommended. async with AsyncSession() as s: r \= await s.get("https://example.com") s \= AsyncSession() \# it also works. _async_ request(_method: str, url: str, params: ~typing.Dict | ~typing.List | ~typing.Tuple | None \= None, data: ~typing.Dict\[str, str\] | ~typing.List\[~typing.Tuple\] | str | ~\_io.BytesIO | bytes | None \= None, json: dict | None \= None, headers: ~curl\_cffi.requests.headers.Headers | ~collections.abc.Mapping\[str, str | None\] | ~collections.abc.Mapping\[bytes, bytes | None\] | ~collections.abc.Sequence\[~typing.Tuple\[str, str\]\] | ~collections.abc.Sequence\[~typing.Tuple\[bytes, bytes\]\] | ~collections.abc.Sequence\[str | bytes\] | None \= None, cookies: ~curl\_cffi.requests.cookies.Cookies | ~http.cookiejar.CookieJar | ~typing.Dict\[str, str\] | ~typing.List\[~typing.Tuple\[str, str\]\] | None \= None, files: ~typing.Dict | None \= None, auth: ~typing.Tuple\[str, str\] | None \= None, timeout: float | ~typing.Tuple\[float, float\] | object | None \= , allow\_redirects: bool | None \= None, max\_redirects: int | None \= None, proxies: ~typing.Dict\[str, str\] | None \= None, proxy: str | None \= None, proxy\_auth: ~typing.Tuple\[str, str\] | None \= None, verify: bool | None \= None, referer: str | None \= None, accept\_encoding: str | None \= 'gzip, deflate, br', content\_callback: ~typing.Callable | None \= None, impersonate: str | ~curl\_cffi.requests.impersonate.BrowserType | None \= None, ja3: str | None \= None, akamai: str | None \= None, extra\_fp: ~curl\_cffi.requests.impersonate.ExtraFingerprints | ~curl\_cffi.requests.impersonate.ExtraFpDict | None \= None, default\_headers: bool | None \= None, default\_encoding: str | ~typing.Callable\[\[bytes\], str\] \= 'utf-8', http\_version: ~curl\_cffi.const.CurlHttpVersion | None \= None, interface: str | None \= None, cert: str | ~typing.Tuple\[str, str\] | None \= None, stream: bool \= False, max\_recv\_speed: int \= 0, multipart: ~curl\_cffi.curl.CurlMime | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/session.html#AsyncSession.request) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.AsyncSession.request "Link to this definition") Send the request, see `curl_cffi.requests.request` for details on parameters. stream(_\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/session.html#AsyncSession.stream) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.AsyncSession.stream "Link to this definition") Equivalent to `async with request(..., stream=True) as r:` _async_ close() → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/session.html#AsyncSession.close) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.AsyncSession.close "Link to this definition") Close the session. _async_ ws\_connect(_url_, _\*args_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/session.html#AsyncSession.ws_connect) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.AsyncSession.ws_connect "Link to this definition") ### Headers[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#headers "Link to this heading") _class_ curl\_cffi.requests.Headers(_headers: [Headers](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Headers "curl_cffi.requests.headers.Headers") | Mapping\[str, str | None\] | Mapping\[bytes, bytes | None\] | Sequence\[Tuple\[str, str\]\] | Sequence\[Tuple\[bytes, bytes\]\] | Sequence\[str | bytes\] | None \= None_, _encoding: str | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/headers.html#Headers) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Headers "Link to this definition") HTTP headers, as a case-insensitive multi-dict. _property_ encoding_: str_[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Headers.encoding "Link to this definition") Header encoding is mandated as ascii, but we allow fallbacks to utf-8 or iso-8859-1. raw()[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Headers.raw "Link to this definition") Returns a list of the raw header items, as byte pairs. multi\_items() → List\[Tuple\[str, str\]\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/headers.html#Headers.multi_items) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Headers.multi_items "Link to this definition") Return a list of (key, value) pairs of headers. Allow multiple occurrences of the same key without concatenating into a single comma separated value. get(_key: str_, _default: Any \= None_) → Any[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/headers.html#Headers.get) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Headers.get "Link to this definition") Return a header value. If multiple occurrences of the header occur then concatenate them together with commas. get\_list(_key: str_, _split\_commas: bool \= False_) → List\[str\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/headers.html#Headers.get_list) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Headers.get_list "Link to this definition") Return a list of all header values for a given key. If split\_commas=True is passed, then any comma separated header values are split into multiple return strings. update(\[_E_, \]_\*\*F_) → None.  Update D from mapping/iterable E and F.[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/headers.html#Headers.update) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Headers.update "Link to this definition") If E present and has a .keys() method, does: for k in E: D\[k\] = E\[k\] If E present and lacks .keys() method, does: for (k, v) in E: D\[k\] = v In either case, this is followed by: for k, v in F.items(): D\[k\] = v \_\_getitem\_\_(_key: str_) → str[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/headers.html#Headers.__getitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Headers.__getitem__ "Link to this definition") Return a single header value. If there are multiple headers with the same key, then we concatenate them with commas. See: [https://tools.ietf.org/html/rfc7230#section-3.2.2](https://tools.ietf.org/html/rfc7230#section-3.2.2) \_\_setitem\_\_(_key: str_, _value: str_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/headers.html#Headers.__setitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Headers.__setitem__ "Link to this definition") Set the header key to value, removing any duplicate entries. Retains insertion order. \_\_delitem\_\_(_key: str_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/headers.html#Headers.__delitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Headers.__delitem__ "Link to this definition") Remove the header key. ### Cookies[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#cookies "Link to this heading") _class_ curl\_cffi.requests.Cookies(_cookies: [Cookies](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Cookies "curl_cffi.requests.cookies.Cookies") | CookieJar | Dict\[str, str\] | List\[Tuple\[str, str\]\] | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/cookies.html#Cookies) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Cookies "Link to this definition") HTTP Cookies, as a mutable mapping. set(_name: str_, _value: str_, _domain: str \= ''_, _path: str \= '/'_, _secure\=False_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/cookies.html#Cookies.set) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Cookies.set "Link to this definition") Set a cookie value by name. May optionally include domain and path. get(_name: str_, _default: str | None \= None_, _domain: str | None \= None_, _path: str | None \= None_) → str | None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/cookies.html#Cookies.get) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Cookies.get "Link to this definition") Get a cookie by name. May optionally include domain and path in order to specify exactly which cookie to retrieve. delete(_name: str_, _domain: str | None \= None_, _path: str | None \= None_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/cookies.html#Cookies.delete) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Cookies.delete "Link to this definition") Delete a cookie by name. May optionally include domain and path in order to specify exactly which cookie to delete. clear(_domain: str | None \= None_, _path: str | None \= None_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/cookies.html#Cookies.clear) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Cookies.clear "Link to this definition") Delete all cookies. Optionally include a domain and path in order to only delete a subset of all the cookies. update(\[_E_, \]_\*\*F_) → None.  Update D from mapping/iterable E and F.[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/cookies.html#Cookies.update) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Cookies.update "Link to this definition") If E present and has a .keys() method, does: for k in E: D\[k\] = E\[k\] If E present and lacks .keys() method, does: for (k, v) in E: D\[k\] = v In either case, this is followed by: for k, v in F.items(): D\[k\] = v \_\_getitem\_\_(_name: str_) → str[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/cookies.html#Cookies.__getitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Cookies.__getitem__ "Link to this definition") \_\_setitem\_\_(_name: str_, _value: str_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/cookies.html#Cookies.__setitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Cookies.__setitem__ "Link to this definition") \_\_delitem\_\_(_name: str_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/cookies.html#Cookies.__delitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Cookies.__delitem__ "Link to this definition") ### Request, Response and WebSocket[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#request-response-and-websocket "Link to this heading") _class_ curl\_cffi.requests.Request(_url: str_, _headers: [Headers](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Headers "curl_cffi.requests.headers.Headers") _, _method: str_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/models.html#Request) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Request "Link to this definition") Representing a sent request. _class_ curl\_cffi.requests.Response(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_, _request: [Request](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Request "curl_cffi.requests.models.Request") | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/models.html#Response) [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response "Link to this definition") Contains information the server sends. url[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.url "Link to this definition") url used in the request. content[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.content "Link to this definition") response body in bytes. text[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.text "Link to this definition") response body in str. status\_code[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.status_code "Link to this definition") http status code. reason[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.reason "Link to this definition") http response reason, such as OK, Not Found. ok[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.ok "Link to this definition") is status\_code in \[200, 400)?\ \ headers[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.headers "Link to this definition")\ \ response headers.\ \ cookies[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.cookies "Link to this definition")\ \ response cookies.\ \ elapsed[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.elapsed "Link to this definition")\ \ how many seconds the request cost.\ \ encoding[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.encoding "Link to this definition")\ \ http body encoding.\ \ charset[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.charset "Link to this definition")\ \ alias for encoding.\ \ primary\_ip[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.primary_ip "Link to this definition")\ \ primary ip of the server.\ \ local\_ip[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.local_ip "Link to this definition")\ \ local ip used in this connection.\ \ charset\_encoding[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.charset_encoding "Link to this definition")\ \ encoding specified by the Content-Type header.\ \ default\_encoding[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.default_encoding "Link to this definition")\ \ 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.\ \ redirect\_count[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.redirect_count "Link to this definition")\ \ how many redirects happened.\ \ redirect\_url[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.redirect_url "Link to this definition")\ \ the final redirected url.\ \ http\_version[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.http_version "Link to this definition")\ \ http version used.\ \ history[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.history "Link to this definition")\ \ history redirections, only headers are available.\ \ raise\_for\_status()[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/models.html#Response.raise_for_status)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.raise_for_status "Link to this definition")\ \ Raise an error if status code is not in \[200, 400)\ \ iter\_lines(_chunk\_size\=None_, _decode\_unicode\=False_, _delimiter\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/models.html#Response.iter_lines)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.iter_lines "Link to this definition")\ \ iterate streaming content line by line, separated by `\n`.\ \ Copied from: [https://requests.readthedocs.io/en/latest/\_modules/requests/models/](https://requests.readthedocs.io/en/latest/_modules/requests/models/)\ which is under the License: Apache 2.0\ \ iter\_content(_chunk\_size\=None_, _decode\_unicode\=False_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/models.html#Response.iter_content)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.iter_content "Link to this definition")\ \ iterate streaming content chunk by chunk in bytes.\ \ json(_\*\*kw_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/models.html#Response.json)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.json "Link to this definition")\ \ return a parsed json object of the content.\ \ close()[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/models.html#Response.close)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.close "Link to this definition")\ \ Close the streaming connection, only valid in stream mode.\ \ _async_ aiter\_lines(_chunk\_size\=None_, _decode\_unicode\=False_, _delimiter\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/models.html#Response.aiter_lines)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.aiter_lines "Link to this definition")\ \ iterate streaming content line by line, separated by `\n`.\ \ Copied from: [https://requests.readthedocs.io/en/latest/\_modules/requests/models/](https://requests.readthedocs.io/en/latest/_modules/requests/models/)\ which is under the License: Apache 2.0\ \ _async_ aiter\_content(_chunk\_size\=None_, _decode\_unicode\=False_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/models.html#Response.aiter_content)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.aiter_content "Link to this definition")\ \ iterate streaming content chunk by chunk in bytes.\ \ _async_ atext() → str[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/models.html#Response.atext)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.atext "Link to this definition")\ \ Return a decoded string.\ \ _async_ acontent() → bytes[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/models.html#Response.acontent)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.acontent "Link to this definition")\ \ wait and read the streaming content in one bytes object.\ \ _async_ aclose()[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/models.html#Response.aclose)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.Response.aclose "Link to this definition")\ \ Close the streaming connection, only valid in stream mode.\ \ _class_ curl\_cffi.requests.WebSocket(_session_, _curl_, _on\_message: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ , bytes\], None\] | None \= None_, _on\_error: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ , CurlError\], None\] | None \= None_, _on\_open: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ \], None\] | None \= None_, _on\_close: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ , int, str\], None\] | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/websockets.html#WebSocket)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.WebSocket "Link to this definition")\ \ \_\_init\_\_(_session_, _curl_, _on\_message: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ , bytes\], None\] | None \= None_, _on\_error: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ , CurlError\], None\] | None \= None_, _on\_open: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ \], None\] | None \= None_, _on\_close: Callable\[\[[WebSocket](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket")\ , int, str\], None\] | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/websockets.html#WebSocket.__init__)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.WebSocket.__init__ "Link to this definition")\ \ recv() → Tuple\[bytes, int\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/websockets.html#WebSocket.recv)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.WebSocket.recv "Link to this definition")\ \ Receive a frame as bytes.\ \ libcurl split frames into fragments, so we have to collect all the chunks for a frame.\ \ send(_payload: bytes_, _flags: [CurlWsFlag](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.CurlWsFlag "curl_cffi.const.CurlWsFlag")\ \= CurlWsFlag.BINARY_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/websockets.html#WebSocket.send)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.WebSocket.send "Link to this definition")\ \ Send a data frame\ \ run\_forever()[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/websockets.html#WebSocket.run_forever)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.WebSocket.run_forever "Link to this definition")\ \ libcurl automatically handles pings and pongs.\ \ ref: [https://curl.se/libcurl/c/libcurl-ws.html](https://curl.se/libcurl/c/libcurl-ws.html)\ \ close(_code: int \= WsCloseCode.OK_, _message: bytes \= b''_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/websockets.html#WebSocket.close)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.WebSocket.close "Link to this definition")\ \ _async_ arecv() → Tuple\[bytes, int\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/websockets.html#WebSocket.arecv)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.WebSocket.arecv "Link to this definition")\ \ _async_ asend(_payload: bytes_, _flags: [CurlWsFlag](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.CurlWsFlag "curl_cffi.const.CurlWsFlag")\ \= CurlWsFlag.BINARY_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.7.0/_modules/curl_cffi/requests/websockets.html#WebSocket.asend)\ [¶](https://curl-cffi.readthedocs.io/en/v0.7.0/api.html#curl_cffi.requests.WebSocket.asend "Link to this definition")\ \ [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.0/index.html)\ \ ====================================================================\ \ ### 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#)\ * [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)\ \ \ ### Related Topics\ \ * [Documentation overview](https://curl-cffi.readthedocs.io/en/v0.7.0/index.html)\ * Previous: [FAQ](https://curl-cffi.readthedocs.io/en/v0.7.0/faq.html "previous chapter")\ \ * Next: [Change Log](https://curl-cffi.readthedocs.io/en/v0.7.0/changelog.html "next chapter")\ \ \ ### Quick search --- # API References — curl_cffi documentation API References[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#api-references "Link to this heading") ============================================================================================================== curl low levl APIs[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl-low-levl-apis "Link to this heading") ---------------------------------------------------------------------------------------------------------------------- ### Curl[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/_modules/curl_cffi/curl.html#Curl) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/_modules/curl_cffi/curl.html#Curl.__init__) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/_modules/curl_cffi/curl.html#Curl.debug) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.Curl.debug "Link to this definition") Set debug to True setopt(_option: [CurlOpt](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlOpt "curl_cffi.const.CurlOpt") _, _value: Any_) → int[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/curl.html#Curl.setopt) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/api.html#curl_cffi.CurlInfo "curl_cffi.const.CurlInfo") _) → bytes | int | float | list[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/curl.html#Curl.getinfo) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/_modules/curl_cffi/curl.html#Curl.version) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/_modules/curl_cffi/curl.html#Curl.impersonate) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/curl.html#Curl.perform) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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 Raises: **CurlError** – if the perform was not successful. duphandle() → [Curl](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") [\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/curl.html#Curl.duphandle) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/_modules/curl_cffi/curl.html#Curl.reset) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/_modules/curl_cffi/curl.html#Curl.parse_cookie_headers) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/_modules/curl_cffi/curl.html#Curl.get_reason_phrase) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/api.html#curl_cffi.CurlHttpVersion "curl_cffi.const.CurlHttpVersion")\ , int, bytes\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/curl.html#Curl.parse_status_line) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/_modules/curl_cffi/curl.html#Curl.close) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.Curl.close "Link to this definition") Close and cleanup curl handle, wrapper for `curl_easy_cleanup`. ws\_recv(_n: int \= 1024_) → tuple\[bytes, CurlWsFrame\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/curl.html#Curl.ws_recv) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.Curl.ws_recv "Link to this definition") Receive a frame from a websocket connection. Parameters: **n** – maximum data to receive. 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/v0.11.0/api.html#curl_cffi.CurlWsFlag "curl_cffi.const.CurlWsFlag") \= CurlWsFlag.BINARY_) → int[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/curl.html#Curl.ws_send) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/_modules/curl_cffi/curl.html#Curl.ws_close) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/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/v0.11.0/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/v0.11.0/api.html#asynccurl "Link to this heading") _class_ curl\_cffi.AsyncCurl(_cacert: str \= ''_, _loop\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/aio.html#AsyncCurl) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/_modules/curl_cffi/aio.html#AsyncCurl.__init__) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") _)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/aio.html#AsyncCurl.add_handle) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") _)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/aio.html#AsyncCurl.remove_handle) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") _)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/aio.html#AsyncCurl.set_result) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") _, _exception_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/aio.html#AsyncCurl.set_exception) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/_modules/curl_cffi/aio.html#AsyncCurl.setopt) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/_modules/curl_cffi/aio.html#AsyncCurl.socket_action) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.AsyncCurl.socket_action "Link to this definition") Call libcurl socket\_action function process\_data(_sockfd: int_, _ev\_bitmask: int_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/aio.html#AsyncCurl.process_data) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/_modules/curl_cffi/aio.html#AsyncCurl.close) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/api.html#curlmime "Link to this heading") _class_ curl\_cffi.CurlMime(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/curl.html#CurlMime) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlMime "Link to this definition") Wrapper for the `curl_mime_` API. \_\_init\_\_(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/curl.html#CurlMime.__init__) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/_modules/curl_cffi/curl.html#CurlMime.addpart) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/_modules/curl_cffi/curl.html#CurlMime.from_list) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/curl.html#CurlMime.attach) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/_modules/curl_cffi/curl.html#CurlMime.close) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/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/v0.11.0/_modules/curl_cffi/const.html#CurlOpt) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/_modules/curl_cffi/const.html#CurlInfo) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/_modules/curl_cffi/const.html#CurlMOpt) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/_modules/curl_cffi/const.html#CurlECode) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/_modules/curl_cffi/const.html#CurlHttpVersion) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/_modules/curl_cffi/const.html#CurlWsFlag) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/_modules/curl_cffi/const.html#CurlSslVersion) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlSslVersion "Link to this definition") `CURL_SSLVERSION` constants from libcurl, see comments for details. requests API[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#requests-api "Link to this heading") ---------------------------------------------------------------------------------------------------------- ### request method[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/api.html#curl_cffi.requests.Response "curl_cffi.requests.models.Response") [\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests.html#request) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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. Returns: A `Response` object. ### Sessions[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#sessions "Link to this heading") _class_ curl\_cffi.requests.Session(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/_modules/curl_cffi/requests/session.html#Session) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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/v0.11.0/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/v0.11.0/_modules/curl_cffi/requests/session.html#Session.__init__) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/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. 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 \= , allow\_redirects: bool | None \= None, max\_redirects: int | None \= None, proxies: dict\[str, str\] | None \= None, proxy: str | None \= None, proxy\_auth: tuple\[str, str\] | None \= None, verify: bool | None \= None, referer: str | None \= None, accept\_encoding: str | None \= 'gzip, deflate, br', content\_callback: ~typing.Callable | None \= None, impersonate: ~typing.Literal\['edge99', 'edge101', 'chrome99', 'chrome100', 'chrome101', 'chrome104', 'chrome107', 'chrome110', 'chrome116', 'chrome119', 'chrome120', 'chrome123', 'chrome124', 'chrome131', 'chrome133a', 'chrome136', 'chrome99\_android', 'chrome131\_android', 'safari153', 'safari155', 'safari170', 'safari172\_ios', 'safari180', 'safari180\_ios', 'safari184', 'safari184\_ios', 'firefox133', 'firefox135', 'tor145', 'chrome', 'edge', 'safari', 'safari\_ios', 'chrome\_android', 'firefox', 'safari15\_3', 'safari15\_5', 'safari17\_0', 'safari17\_2\_ios', 'safari18\_0', 'safari18\_0\_ios', 'safari18\_4', 'safari18\_4\_ios'\] | None \= None, ja3: str | None \= None, akamai: str | None \= None, extra\_fp: ~curl\_cffi.requests.impersonate.ExtraFingerprints | ~curl\_cffi.requests.impersonate.ExtraFpDict | None \= None, default\_headers: bool | None \= None, default\_encoding: str | ~typing.Callable\[\[bytes\], str\] \= 'utf-8', quote: str | ~typing.Literal\[False\] \= '', http\_version: ~curl\_cffi.const.CurlHttpVersion | None \= None, interface: str | None \= None, cert: str | tuple\[str, str\] | None \= None, stream: bool | None \= None, max\_recv\_speed: int \= 0, multipart: ~curl\_cffi.curl.CurlMime | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/session.html#Session.request) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Session.request "Link to this definition") Send the request, see `requests.request` for details on parameters. stream(_method: Literal\['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD', 'TRACE', 'PATCH', 'QUERY'\]_, _url: str_, _\*\*kwargs: None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/session.html#Session.stream) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Session.stream "Link to this definition") Equivalent to `with request(..., stream=True) as r:` ws\_connect(_url_, _on\_message\=None_, _on\_error\=None_, _on\_open\=None_, _on\_close\=None_, _\*\*kwargs_) → [WebSocket](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.WebSocket "curl_cffi.requests.websockets.WebSocket") [\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/session.html#Session.ws_connect) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Session.ws_connect "Link to this definition") Connects to a websocket url. Note: This method is deprecated, use WebSocket instead. Parameters: * **url** – the ws url to connect. * **on\_message** – message callback, `def on_message(ws, str)` * **on\_error** – error callback, `def on_error(ws, error)` * **on\_open** – open callback, `def on_open(ws)` * **on\_close** – close callback, `def on_close(ws)` Other parameters are the same as `.request` Returns: a WebSocket instance to communicate with the server. _class_ curl\_cffi.requests.AsyncSession(_\*_, _loop\=None_, _async\_curl: [AsyncCurl](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.AsyncCurl "curl_cffi.AsyncCurl") | None \= None_, _max\_clients: int \= 10_, _\*\*kwargs: Unpack\[BaseSessionParams\[R\]\]_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/session.html#AsyncSession) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.AsyncSession "Link to this definition") An async request session, cookies and connections will be reused. \_\_init\_\_(_\*_, _loop\=None_, _async\_curl: [AsyncCurl](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.AsyncCurl "curl_cffi.AsyncCurl") | None \= None_, _max\_clients: int \= 10_, _\*\*kwargs: Unpack\[BaseSessionParams\[R\]\]_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/session.html#AsyncSession.__init__) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.AsyncSession.__init__ "Link to this definition") Parameters set in the `__init__` method will be override by the same parameter in request method. Parameters: * **loop** – loop to use, if not provided, the running loop will be used. * **async\_curl** – \[AsyncCurl\](/api/curl\_cffi#curl\_cffi.AsyncCurl) object to use. * **max\_clients** – maxmium curl handle to use in the session, this will affect the concurrency ratio. * **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 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. * **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. Notes This class can be used as a context manager, and it’s recommended to use via `async with`. However, unlike aiohttp, it is not required to use `with`. from curl\_cffi.requests import AsyncSession \# recommended. async with AsyncSession() as s: r \= await s.get("https://example.com") s \= AsyncSession() \# it also works. _async_ 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 \= , allow\_redirects: bool | None \= None, max\_redirects: int | None \= None, proxies: dict\[str, str\] | None \= None, proxy: str | None \= None, proxy\_auth: tuple\[str, str\] | None \= None, verify: bool | None \= None, referer: str | None \= None, accept\_encoding: str | None \= 'gzip, deflate, br', content\_callback: ~typing.Callable | None \= None, impersonate: ~typing.Literal\['edge99', 'edge101', 'chrome99', 'chrome100', 'chrome101', 'chrome104', 'chrome107', 'chrome110', 'chrome116', 'chrome119', 'chrome120', 'chrome123', 'chrome124', 'chrome131', 'chrome133a', 'chrome136', 'chrome99\_android', 'chrome131\_android', 'safari153', 'safari155', 'safari170', 'safari172\_ios', 'safari180', 'safari180\_ios', 'safari184', 'safari184\_ios', 'firefox133', 'firefox135', 'tor145', 'chrome', 'edge', 'safari', 'safari\_ios', 'chrome\_android', 'firefox', 'safari15\_3', 'safari15\_5', 'safari17\_0', 'safari17\_2\_ios', 'safari18\_0', 'safari18\_0\_ios', 'safari18\_4', 'safari18\_4\_ios'\] | None \= None, ja3: str | None \= None, akamai: str | None \= None, extra\_fp: ~curl\_cffi.requests.impersonate.ExtraFingerprints | ~curl\_cffi.requests.impersonate.ExtraFpDict | None \= None, default\_headers: bool | None \= None, default\_encoding: str | ~typing.Callable\[\[bytes\], str\] \= 'utf-8', quote: str | ~typing.Literal\[False\] \= '', http\_version: ~curl\_cffi.const.CurlHttpVersion | None \= None, interface: str | None \= None, cert: str | tuple\[str, str\] | None \= None, stream: bool | None \= None, max\_recv\_speed: int \= 0, multipart: ~curl\_cffi.curl.CurlMime | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/session.html#AsyncSession.request) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.AsyncSession.request "Link to this definition") Send the request, see `curl_cffi.requests.request` for details on args. stream(_method: Literal\['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD', 'TRACE', 'PATCH', 'QUERY'\]_, _url: str_, _\*\*kwargs: None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/session.html#AsyncSession.stream) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.AsyncSession.stream "Link to this definition") Equivalent to `async with request(..., stream=True) as r:` _async_ close() → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/session.html#AsyncSession.close) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.AsyncSession.close "Link to this definition") Close the session. _async_ ws\_connect(_url: str_, _autoclose: bool \= True_, _params: dict | list | tuple | 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_, _auth: tuple\[str_, _str\] | None \= None_, _timeout: float | tuple\[float_, _float\] | object | None \= _, _allow\_redirects: bool | None \= None_, _max\_redirects: int | None \= None_, _proxies: dict\[str_, _str\] | None \= None_, _proxy: str | None \= None_, _proxy\_auth: tuple\[str_, _str\] | None \= None_, _verify: bool | None \= None_, _referer: str | None \= None_, _accept\_encoding: str | None \= 'gzip_, _deflate_, _br'_, _impersonate: ~typing.Literal\['edge99'_, _'edge101'_, _'chrome99'_, _'chrome100'_, _'chrome101'_, _'chrome104'_, _'chrome107'_, _'chrome110'_, _'chrome116'_, _'chrome119'_, _'chrome120'_, _'chrome123'_, _'chrome124'_, _'chrome131'_, _'chrome133a'_, _'chrome136'_, _'chrome99\_android'_, _'chrome131\_android'_, _'safari153'_, _'safari155'_, _'safari170'_, _'safari172\_ios'_, _'safari180'_, _'safari180\_ios'_, _'safari184'_, _'safari184\_ios'_, _'firefox133'_, _'firefox135'_, _'tor145'_, _'chrome'_, _'edge'_, _'safari'_, _'safari\_ios'_, _'chrome\_android'_, _'firefox'_, _'safari15\_3'_, _'safari15\_5'_, _'safari17\_0'_, _'safari17\_2\_ios'_, _'safari18\_0'_, _'safari18\_0\_ios'_, _'safari18\_4'_, _'safari18\_4\_ios'\] | None \= None_, _ja3: str | None \= None_, _akamai: str | None \= None_, _extra\_fp: ~curl\_cffi.requests.impersonate.ExtraFingerprints | ~curl\_cffi.requests.impersonate.ExtraFpDict | None \= None_, _default\_headers: bool | None \= None_, _quote: str | ~typing.Literal\[False\] \= ''_, _http\_version: ~curl\_cffi.const.CurlHttpVersion | None \= None_, _interface: str | None \= None_, _cert: str | tuple\[str_, _str\] | None \= None_, _max\_recv\_speed: int \= 0_) → [AsyncWebSocket](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.AsyncWebSocket "curl_cffi.requests.websockets.AsyncWebSocket") [\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/session.html#AsyncSession.ws_connect) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.AsyncSession.ws_connect "Link to this definition") Connects to a WebSocket. Parameters: * **url** – url for the requests. * **autoclose** – whether to close the WebSocket after receiving a close frame. * **params** – query string for the requests. * **headers** – headers to send. * **cookies** – cookies to use. * **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. * **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 str. * **default\_headers** – whether to set default browser headers. * **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. * **interface** – which interface to use. * **cert** – a tuple of (cert, key) filenames for client cert. * **max\_recv\_speed** – maximum receive speed, bytes per second. ### Headers[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#headers "Link to this heading") _class_ curl\_cffi.requests.Headers(_headers: [Headers](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Headers "curl_cffi.requests.headers.Headers") | Mapping\[str, str | None\] | Mapping\[bytes, bytes | None\] | Sequence\[tuple\[str, str\]\] | Sequence\[tuple\[bytes, bytes\]\] | Sequence\[str | bytes\] | None \= None_, _encoding: str | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/headers.html#Headers) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Headers "Link to this definition") HTTP headers, as a case-insensitive multi-dict. _property_ encoding_: str_[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Headers.encoding "Link to this definition") Header encoding is mandated as ascii, but we allow fallbacks to utf-8 or iso-8859-1. raw()[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Headers.raw "Link to this definition") Returns a list of the raw header items, as byte pairs. multi\_items() → list\[tuple\[str, str | None\]\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/headers.html#Headers.multi_items) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Headers.multi_items "Link to this definition") Return a list of (key, value) pairs of headers. Allow multiple occurrences of the same key without concatenating into a single comma separated value. get(_key: str_, _default: Any \= None_) → Any[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/headers.html#Headers.get) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Headers.get "Link to this definition") Return a header value. If multiple occurrences of the header occur then concatenate them together with commas. get\_list(_key: str_, _split\_commas: bool \= False_) → list\[str | None\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/headers.html#Headers.get_list) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Headers.get_list "Link to this definition") Return a list of all header values for a given key. If split\_commas=True is passed, then any comma separated header values are split into multiple return strings. update(\[_E_, \]_\*\*F_) → None.  Update D from mapping/iterable E and F.[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/headers.html#Headers.update) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Headers.update "Link to this definition") If E present and has a .keys() method, does: for k in E: D\[k\] = E\[k\] If E present and lacks .keys() method, does: for (k, v) in E: D\[k\] = v In either case, this is followed by: for k, v in F.items(): D\[k\] = v \_\_getitem\_\_(_key: str_) → str | None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/headers.html#Headers.__getitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Headers.__getitem__ "Link to this definition") Return a single header value. If there are multiple headers with the same key, then we concatenate them with commas. See: [https://tools.ietf.org/html/rfc7230#section-3.2.2](https://tools.ietf.org/html/rfc7230#section-3.2.2) \_\_setitem\_\_(_key: str_, _value: str | None_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/headers.html#Headers.__setitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Headers.__setitem__ "Link to this definition") Set the header key to value, removing any duplicate entries. Retains insertion order. \_\_delitem\_\_(_key: str_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/headers.html#Headers.__delitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Headers.__delitem__ "Link to this definition") Remove the header key. ### Cookies[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#cookies "Link to this heading") _class_ curl\_cffi.requests.Cookies(_cookies: [Cookies](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Cookies "curl_cffi.requests.cookies.Cookies") | CookieJar | dict\[str, str\] | list\[tuple\[str, str\]\] | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/cookies.html#Cookies) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Cookies "Link to this definition") HTTP Cookies, as a mutable mapping. set(_name: str_, _value: str_, _domain: str \= ''_, _path: str \= '/'_, _secure\=False_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/cookies.html#Cookies.set) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Cookies.set "Link to this definition") Set a cookie value by name. May optionally include domain and path. get(_name: str_, _default: str | None \= None_, _domain: str | None \= None_, _path: str | None \= None_) → str | None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/cookies.html#Cookies.get) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Cookies.get "Link to this definition") Get a cookie by name. May optionally include domain and path in order to specify exactly which cookie to retrieve. delete(_name: str_, _domain: str | None \= None_, _path: str | None \= None_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/cookies.html#Cookies.delete) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Cookies.delete "Link to this definition") Delete a cookie by name. May optionally include domain and path in order to specify exactly which cookie to delete. clear(_domain: str | None \= None_, _path: str | None \= None_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/cookies.html#Cookies.clear) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Cookies.clear "Link to this definition") Delete all cookies. Optionally include a domain and path in order to only delete a subset of all the cookies. update(\[_E_, \]_\*\*F_) → None.  Update D from mapping/iterable E and F.[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/cookies.html#Cookies.update) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Cookies.update "Link to this definition") If E present and has a .keys() method, does: for k in E: D\[k\] = E\[k\] If E present and lacks .keys() method, does: for (k, v) in E: D\[k\] = v In either case, this is followed by: for k, v in F.items(): D\[k\] = v \_\_getitem\_\_(_name: str_) → str[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/cookies.html#Cookies.__getitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Cookies.__getitem__ "Link to this definition") \_\_setitem\_\_(_name: str_, _value: str_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/cookies.html#Cookies.__setitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Cookies.__setitem__ "Link to this definition") \_\_delitem\_\_(_name: str_) → None[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/cookies.html#Cookies.__delitem__) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Cookies.__delitem__ "Link to this definition") ### Request, Response and WebSocket[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#request-response-and-websocket "Link to this heading") _class_ curl\_cffi.requests.Request(_url: str_, _headers: [Headers](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Headers "curl_cffi.requests.headers.Headers") _, _method: str_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/models.html#Request) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Request "Link to this definition") Representing a sent request. _class_ curl\_cffi.requests.Response(_curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.Curl "curl_cffi.curl.Curl") | None \= None_, _request: [Request](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Request "curl_cffi.requests.models.Request") | None \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/models.html#Response) [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response "Link to this definition") Contains information the server sends. url[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.url "Link to this definition") url used in the request. content[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.content "Link to this definition") response body in bytes. text[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.text "Link to this definition") response body in str. status\_code[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.status_code "Link to this definition") http status code. reason[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.reason "Link to this definition") http response reason, such as OK, Not Found. ok[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.ok "Link to this definition") is status\_code in \[200, 400)?\ \ headers[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.headers "Link to this definition")\ \ response headers.\ \ cookies[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.cookies "Link to this definition")\ \ response cookies.\ \ elapsed[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.elapsed "Link to this definition")\ \ how many seconds the request cost.\ \ encoding[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.encoding "Link to this definition")\ \ http body encoding.\ \ charset[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.charset "Link to this definition")\ \ alias for encoding.\ \ primary\_ip[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.primary_ip "Link to this definition")\ \ primary ip of the server.\ \ primary\_port[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.primary_port "Link to this definition")\ \ primary port of the server.\ \ local\_ip[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.local_ip "Link to this definition")\ \ local ip used in this connection.\ \ local\_port[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.local_port "Link to this definition")\ \ local port used in this connection.\ \ charset\_encoding[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.charset_encoding "Link to this definition")\ \ encoding specified by the Content-Type header.\ \ default\_encoding[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.default_encoding "Link to this definition")\ \ 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.\ \ redirect\_count[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.redirect_count "Link to this definition")\ \ how many redirects happened.\ \ redirect\_url[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.redirect_url "Link to this definition")\ \ the final redirected url.\ \ http\_version[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.http_version "Link to this definition")\ \ http version used.\ \ history[¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.history "Link to this definition")\ \ history redirections, only headers are available.\ \ raise\_for\_status()[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/models.html#Response.raise_for_status)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.raise_for_status "Link to this definition")\ \ Raise an error if status code is not in \[200, 400)\ \ iter\_lines(_chunk\_size\=None_, _decode\_unicode\=False_, _delimiter\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/models.html#Response.iter_lines)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.iter_lines "Link to this definition")\ \ iterate streaming content line by line, separated by `\n`.\ \ Copied from: [https://requests.readthedocs.io/en/latest/\_modules/requests/models/](https://requests.readthedocs.io/en/latest/_modules/requests/models/)\ which is under the License: Apache 2.0\ \ iter\_content(_chunk\_size\=None_, _decode\_unicode\=False_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/models.html#Response.iter_content)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.iter_content "Link to this definition")\ \ iterate streaming content chunk by chunk in bytes.\ \ json(_\*\*kw_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/models.html#Response.json)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.json "Link to this definition")\ \ return a parsed json object of the content.\ \ close()[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/models.html#Response.close)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.close "Link to this definition")\ \ Close the streaming connection, only valid in stream mode.\ \ _async_ aiter\_lines(_chunk\_size\=None_, _decode\_unicode\=False_, _delimiter\=None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/models.html#Response.aiter_lines)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.aiter_lines "Link to this definition")\ \ iterate streaming content line by line, separated by `\n`.\ \ Copied from: [https://requests.readthedocs.io/en/latest/\_modules/requests/models/](https://requests.readthedocs.io/en/latest/_modules/requests/models/)\ which is under the License: Apache 2.0\ \ _async_ aiter\_content(_chunk\_size\=None_, _decode\_unicode\=False_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/models.html#Response.aiter_content)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.aiter_content "Link to this definition")\ \ iterate streaming content chunk by chunk in bytes.\ \ _async_ atext() → str[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/models.html#Response.atext)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.atext "Link to this definition")\ \ Return a decoded string.\ \ _async_ acontent() → bytes[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/models.html#Response.acontent)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.acontent "Link to this definition")\ \ wait and read the streaming content in one bytes object.\ \ _async_ aclose()[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/models.html#Response.aclose)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.Response.aclose "Link to this definition")\ \ Close the streaming connection, only valid in stream mode.\ \ _class_ curl\_cffi.requests.WebSocket(_curl: Union\[Curl_, _Any\] \= _, _\*_, _autoclose: bool \= True_, _skip\_utf8\_validation: bool \= False_, _debug: bool \= False_, _on\_open: Optional\[ON\_OPEN\_T\] \= None_, _on\_close: Optional\[ON\_CLOSE\_T\] \= None_, _on\_data: Optional\[ON\_DATA\_T\] \= None_, _on\_message: Optional\[ON\_MESSAGE\_T\] \= None_, _on\_error: Optional\[ON\_ERROR\_T\] \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#WebSocket)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.WebSocket "Link to this definition")\ \ A WebSocket implementation using libcurl.\ \ \_\_init\_\_(_curl: Union\[Curl_, _Any\] \= _, _\*_, _autoclose: bool \= True_, _skip\_utf8\_validation: bool \= False_, _debug: bool \= False_, _on\_open: Optional\[ON\_OPEN\_T\] \= None_, _on\_close: Optional\[ON\_CLOSE\_T\] \= None_, _on\_data: Optional\[ON\_DATA\_T\] \= None_, _on\_message: Optional\[ON\_MESSAGE\_T\] \= None_, _on\_error: Optional\[ON\_ERROR\_T\] \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#WebSocket.__init__)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.WebSocket.__init__ "Link to this definition")\ \ Parameters:\ \ * **autoclose** – whether to close the WebSocket after receiving a close frame.\ \ * **skip\_utf8\_validation** – whether to skip UTF-8 validation for text frames in run\_forever().\ \ * **debug** – print extra curl debug info.\ \ * **on\_open** – open callback, `def on_open(ws)`\ \ * **on\_close** – close callback, `def on_close(ws, code, reason)`\ \ * **on\_data** – raw data receive callback, `def on_data(ws, data, frame)`\ \ * **on\_message** – message receive callback, `def on_message(ws, message)`\ \ * **on\_error** – error callback, `def on_error(ws, exception)`\ \ \ connect(_url: str, params: Optional\[Union\[dict, list, tuple\]\] \= None, headers: Optional\[HeaderTypes\] \= None, cookies: Optional\[CookieTypes\] \= None, auth: Optional\[tuple\[str, str\]\] \= None, timeout: Optional\[Union\[float, tuple\[float, float\], object\]\] \= , allow\_redirects: bool \= True, max\_redirects: int \= 30, proxies: Optional\[ProxySpec\] \= None, proxy: Optional\[str\] \= None, proxy\_auth: Optional\[tuple\[str, str\]\] \= None, verify: Optional\[bool\] \= None, referer: Optional\[str\] \= None, accept\_encoding: Optional\[str\] \= 'gzip, deflate, br', impersonate: Optional\[BrowserTypeLiteral\] \= None, ja3: Optional\[str\] \= None, akamai: Optional\[str\] \= None, extra\_fp: Optional\[Union\[ExtraFingerprints, ExtraFpDict\]\] \= None, default\_headers: bool \= True, quote: Union\[str, Literal\[False\]\] \= '', http\_version: Optional\[CurlHttpVersion\] \= None, interface: Optional\[str\] \= None, cert: Optional\[Union\[str, tuple\[str, str\]\]\] \= None, max\_recv\_speed: int \= 0, curl\_options: Optional\[dict\[CurlOpt, str\]\] \= None_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#WebSocket.connect)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.WebSocket.connect "Link to this definition")\ \ Connect to the WebSocket.\ \ libcurl automatically handles pings and pongs. ref: [https://curl.se/libcurl/c/libcurl-ws.html](https://curl.se/libcurl/c/libcurl-ws.html)\ \ Parameters:\ \ * **url** – url for the requests.\ \ * **params** – query string for the requests.\ \ * **headers** – headers to send.\ \ * **cookies** – cookies to use.\ \ * **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.\ \ * **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 str.\ \ * **default\_headers** – whether to set default browser headers.\ \ * **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.\ \ * **interface** – which interface to use.\ \ * **cert** – a tuple of (cert, key) filenames for client cert.\ \ * **max\_recv\_speed** – maximum receive speed, bytes per second.\ \ * **curl\_options** – extra curl options to use.\ \ \ recv\_fragment() → tuple\[bytes, CurlWsFrame\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#WebSocket.recv_fragment)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.WebSocket.recv_fragment "Link to this definition")\ \ Receive a single frame as bytes.\ \ recv() → tuple\[bytes, int\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#WebSocket.recv)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.WebSocket.recv "Link to this definition")\ \ Receive a frame as bytes.\ \ libcurl splits frames into fragments, so we have to collect all the chunks for a frame.\ \ recv\_str() → str[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#WebSocket.recv_str)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.WebSocket.recv_str "Link to this definition")\ \ Receive a text frame.\ \ recv\_json(_\*, loads: Callable\[\[str\], T\] \= _) → T[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#WebSocket.recv_json)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.WebSocket.recv_json "Link to this definition")\ \ Receive a JSON frame.\ \ Parameters:\ \ **loads** – JSON decoder, default is json.loads.\ \ send(_payload: str | bytes_, _flags: [CurlWsFlag](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlWsFlag "curl_cffi.const.CurlWsFlag")\ \= CurlWsFlag.BINARY_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#WebSocket.send)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.WebSocket.send "Link to this definition")\ \ Send a data frame.\ \ Parameters:\ \ * **payload** – data to send.\ \ * **flags** – flags for the frame.\ \ \ send\_binary(_payload: bytes_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#WebSocket.send_binary)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.WebSocket.send_binary "Link to this definition")\ \ Send a binary frame.\ \ Parameters:\ \ **payload** – binary data to send.\ \ send\_bytes(_payload: bytes_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#WebSocket.send_bytes)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.WebSocket.send_bytes "Link to this definition")\ \ Send a binary frame. Same as [`send_binary()`](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.WebSocket.send_binary "curl_cffi.requests.WebSocket.send_binary")\ .\ \ Parameters:\ \ **payload** – binary data to send.\ \ send\_str(_payload: str_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#WebSocket.send_str)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.WebSocket.send_str "Link to this definition")\ \ Send a text frame.\ \ Parameters:\ \ **payload** – text data to send.\ \ send\_json(_payload: ~typing.Any, \*, dumps: ~typing.Callable\[\[~typing.Any\], str\] \= functools.partial(, separators=(',', ':'))_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#WebSocket.send_json)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.WebSocket.send_json "Link to this definition")\ \ Send a JSON frame.\ \ Parameters:\ \ * **payload** – data to send.\ \ * **dumps** – JSON encoder, default is json.dumps.\ \ \ ping(_payload: str | bytes_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#WebSocket.ping)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.WebSocket.ping "Link to this definition")\ \ Send a ping frame.\ \ Parameters:\ \ **payload** – data to send.\ \ run\_forever(_url: str_, _\*\*kwargs_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#WebSocket.run_forever)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.WebSocket.run_forever "Link to this definition")\ \ Run the WebSocket forever. See [`connect()`](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.WebSocket.connect "curl_cffi.requests.WebSocket.connect")\ for details on parameters.\ \ libcurl automatically handles pings and pongs. ref: [https://curl.se/libcurl/c/libcurl-ws.html](https://curl.se/libcurl/c/libcurl-ws.html)\ \ close(_code: int \= WsCloseCode.OK_, _message: bytes \= b''_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#WebSocket.close)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.WebSocket.close "Link to this definition")\ \ Close the connection.\ \ Parameters:\ \ * **code** – close code.\ \ * **message** – close reason.\ \ \ _class_ curl\_cffi.requests.AsyncWebSocket(_session: [AsyncSession](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.AsyncSession "curl_cffi.requests.AsyncSession")\ _, _curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.Curl "curl_cffi.Curl")\ _, _\*_, _autoclose: bool \= True_, _debug: bool \= False_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.AsyncWebSocket "Link to this definition")\ \ An async WebSocket implementation using libcurl.\ \ \_\_init\_\_(_session: [AsyncSession](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.AsyncSession "curl_cffi.requests.AsyncSession")\ _, _curl: [Curl](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.Curl "curl_cffi.Curl")\ _, _\*_, _autoclose: bool \= True_, _debug: bool \= False_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.__init__)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.AsyncWebSocket.__init__ "Link to this definition")\ \ _async_ recv\_fragment(_\*_, _timeout: float | None \= None_) → tuple\[bytes, CurlWsFrame\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.recv_fragment)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.AsyncWebSocket.recv_fragment "Link to this definition")\ \ Receive a single frame as bytes.\ \ Parameters:\ \ **timeout** – how many seconds to wait before giving up.\ \ _async_ recv(_\*_, _timeout: float | None \= None_) → tuple\[bytes, int\][\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.recv)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.AsyncWebSocket.recv "Link to this definition")\ \ Receive a frame as bytes.\ \ libcurl splits frames into fragments, so we have to collect all the chunks for a frame.\ \ Parameters:\ \ **timeout** – how many seconds to wait before giving up.\ \ _async_ recv\_str(_\*_, _timeout: float | None \= None_) → str[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.recv_str)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.AsyncWebSocket.recv_str "Link to this definition")\ \ Receive a text frame.\ \ Parameters:\ \ **timeout** – how many seconds to wait before giving up.\ \ _async_ recv\_json(_\*, loads: Callable\[\[str\], T\] \= , timeout: Optional\[float\] \= None_) → T[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.recv_json)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.AsyncWebSocket.recv_json "Link to this definition")\ \ Receive a JSON frame.\ \ Parameters:\ \ * **loads** – JSON decoder, default is json.loads.\ \ * **timeout** – how many seconds to wait before giving up.\ \ \ _async_ send(_payload: str | bytes_, _flags: [CurlWsFlag](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.CurlWsFlag "curl_cffi.const.CurlWsFlag")\ \= CurlWsFlag.BINARY_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.send)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.AsyncWebSocket.send "Link to this definition")\ \ Send a data frame.\ \ Parameters:\ \ * **payload** – data to send.\ \ * **flags** – flags for the frame.\ \ \ _async_ send\_binary(_payload: bytes_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.send_binary)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.AsyncWebSocket.send_binary "Link to this definition")\ \ Send a binary frame.\ \ Parameters:\ \ **payload** – binary data to send.\ \ _async_ send\_bytes(_payload: bytes_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.send_bytes)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.AsyncWebSocket.send_bytes "Link to this definition")\ \ Send a binary frame. Same as [`send_binary()`](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.AsyncWebSocket.send_binary "curl_cffi.requests.AsyncWebSocket.send_binary")\ .\ \ Parameters:\ \ **payload** – binary data to send.\ \ _async_ send\_str(_payload: str_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.send_str)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.AsyncWebSocket.send_str "Link to this definition")\ \ Send a text frame.\ \ Parameters:\ \ **payload** – text data to send.\ \ _async_ send\_json(_payload: ~typing.Any, \*, dumps: ~typing.Callable\[\[~typing.Any\], str\] \= functools.partial(, separators=(',', ':'))_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.send_json)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.AsyncWebSocket.send_json "Link to this definition")\ \ Send a JSON frame.\ \ Parameters:\ \ * **payload** – data to send.\ \ * **dumps** – JSON encoder, default is json.dumps.\ \ \ _async_ ping(_payload: str | bytes_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.ping)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.AsyncWebSocket.ping "Link to this definition")\ \ Send a ping frame.\ \ Parameters:\ \ **payload** – data to send.\ \ _async_ close(_code: int \= WsCloseCode.OK_, _message: bytes \= b''_)[\[source\]](https://curl-cffi.readthedocs.io/en/v0.11.0/_modules/curl_cffi/requests/websockets.html#AsyncWebSocket.close)\ [¶](https://curl-cffi.readthedocs.io/en/v0.11.0/api.html#curl_cffi.requests.AsyncWebSocket.close "Link to this definition")\ \ Close the connection.\ \ Parameters:\ \ * **code** – close code.\ \ * **message** – close reason.\ \ \ [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.11.0/index.html)\ \ =====================================================================\ \ \ \ ### 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#)\ * [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)\ \ \ ### Related Topics\ \ * [Documentation overview](https://curl-cffi.readthedocs.io/en/v0.11.0/index.html)\ * Previous: [FAQ](https://curl-cffi.readthedocs.io/en/v0.11.0/faq.html "previous chapter")\ \ * Next: [Change Log](https://curl-cffi.readthedocs.io/en/v0.11.0/changelog.html "next chapter") --- # Search — curl_cffi documentation Search ====== Searching for multiple words only shows matches that contain all words. [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.0/index.html) ==================================================================== ### 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/index.html) --- # Compatibility with requests — curl_cffi documentation Compatibility with requests[¶](https://curl-cffi.readthedocs.io/en/v0.7.0/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/yifeikong/curl\_cffi/issues/24](https://github.com/yifeikong/curl_cffi/issues/24) ) * redirect history are not supported, tracked in \[#82\]([https://github.com/yifeikong/curl\_cffi/issues/82](https://github.com/yifeikong/curl_cffi/issues/82) ) * empty-domains cookies may lost during redirects, tracked in \[#55\]([https://github.com/yifeikong/curl\_cffi/issues/55](https://github.com/yifeikong/curl_cffi/issues/55) ) [curl\_cffi](https://curl-cffi.readthedocs.io/en/v0.7.0/index.html) ==================================================================== ### 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/index.html) * Previous: [Advanced Usage](https://curl-cffi.readthedocs.io/en/v0.7.0/advanced.html "previous chapter") * Next: [FAQ](https://curl-cffi.readthedocs.io/en/v0.7.0/faq.html "next chapter") ### Quick search ---