Skip to main content

httpx-curl-cffi

httpx transport for curl_cffi - python binding for curl-impersonate fork

Unlike other pure python http clients like httpx (with native transport) or requests, curl_cffi can impersonate browser's TLS/JA3 and HTTP/2 fingerprints.

Browser simulation implemented by low-level customizations and usage of native browser TLS libraries (BoringSSL for Chrome, nss for Firefox) - which is impossible to achieve with Python's OpenSSL binding.

If you are blocked by some website for no obvious reason, you can give curl_cffi a try.

Install

pip install httpx-curl-cffi

Usage

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}
))

Proxy from environment variables

Note that httpx.Client and httpx.AsyncClient disables proxy configuration from environment variables on providing transport argument even with trust_env=True (default), to have this configured in the same way as native transport use snippet below:

import httpx
from httpx._utils import get_environment_proxies
from httpx_curl_cffi import CurlTransport  # or AsyncCurlTransport

def transport_factory(proxy: httpx.Proxy | None = None) -> httpx.BaseTransport:
    return CurlTransport(  # or AsyncCurlTransport
      proxy=proxy,
      verify=False,  # and other custom options
    )

client = httpx.Client(  # or httpx.AsyncClient
    transport=transport_factory(),
    mounts={
        k: transport_factory(httpx.Proxy(url=v)) if v else None
        for k, v in get_environment_proxies().items()
    }
)

TODO

  • httpx.Request content completely read in memory before sending, not sure if it's fixable with curl_cffi at all
  • CurlTransport.cert argument should support in-memory data instead of filenames, pathlib.Path (instead of strings in httpx._types.CertTypes) is forced

curl_cffi issues

Known limitations

  • httpx.Timeout.write is ignored (libcurl limitation)

  • CurlTransport.verify as ssl.SSLContext isn't supported (because OpenSSL is not used)

  • CurlTransport.trust_env argument is ignored, libcurl is always using environment variables for configuration, which is disabled for proxies using CurlOpt.NOPROXY setting to make proxy argument have complete control on proxy usage, but may have effect in TLS configuration (but may not be used by curl-impersonate fork, idk) https://github.com/lexiforest/curl_cffi/issues/345

  • httpx.Response.request.headers isn't updated with default curl-impersonate headers, which can be unexpected on CurlTransport.default_headers=True https://github.com/lexiforest/curl_cffi/issues/368

  • CurlTransport.cert argument isn't compatible with (deprecated) httpx._types.CertTypes - impossible to pass password as third tuple element, pathlib.Path (instead of strings in httpx._types.CertTypes) is forced

Metadata

Release files for httpx-curl-cffi 0.1.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for httpx-curl-cffi 0.1.5
File Size Uploaded
httpx_curl_cffi-0.1.5.tar.gz 7.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for httpx-curl-cffi 0.1.5
File Interpreter ABI Platform
httpx_curl_cffi-0.1.5-py3-none-any.whl Python 3 none any Details

Total release size: 16.9 kB

Release files / httpx_curl_cffi-0.1.5.tar.gz

Download URL httpx_curl_cffi-0.1.5.tar.gz
Size 7.9 kB
Tags Source
SHA-256 checksum
How to use checksums
177ee9968e9da142407017816cc3fb08ab281b134f773a9359b6a4650a6c81f3
BLAKE2b-256 checksum
How to use checksums
641f158975d2541effa30f0d7634542dce50e8280ab283e7efc8d221ebf8a949
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Dec 2, 2025.

Transparency log

Release files / httpx_curl_cffi-0.1.5-py3-none-any.whl

Download URL httpx_curl_cffi-0.1.5-py3-none-any.whl
Size 8.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
be414a97ac1f627693f4c8a8631f2852bb1c09456e61ff8ad996ad050a11fb53
BLAKE2b-256 checksum
How to use checksums
6e1382039e3df58e0d52a6f82cc73d958400a2777d78c6cd6378c937a707afd0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Dec 2, 2025.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.5 This release

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page