Scraping Central is reader-supported. When you buy through links on our site, we may earn an affiliate commission.

Tutorial

Using curl_cffi for TLS Impersonation in Python Scraping

Learn how to use curl_cffi to impersonate real browser TLS fingerprints in Python web scraping and bypass JA3/JA4 fingerprint detection.

curl_cffi is a Python binding for curl-impersonate that lets you make HTTP requests with TLS fingerprints matching real browsers. It is the best solution when you need HTTP-level scraping but sites block based on TLS fingerprinting.

Installation

pip install curl_cffi

Basic Usage

from curl_cffi import requests

# Impersonate Chrome 136
response = requests.get(
    "https://example.com",
    impersonate="chrome136"
)
print(response.status_code)
print(response.text[:500])

Available Browser Profiles

curl_cffi supports multiple browser impersonation targets:

from curl_cffi import requests

# Chrome versions
response = requests.get(url, impersonate="chrome136")
response = requests.get(url, impersonate="chrome124")
response = requests.get(url, impersonate="chrome120")

# Firefox versions
response = requests.get(url, impersonate="firefox133")

# Safari versions
response = requests.get(url, impersonate="safari18_0")

# Edge
response = requests.get(url, impersonate="edge131")

Using Sessions for Cookie Persistence

from curl_cffi import requests

session = requests.Session(impersonate="chrome136")

# Cookies persist across requests
session.get("https://example.com/login")
response = session.get("https://example.com/dashboard")
print(response.text)

Async Support

curl_cffi supports async operations for concurrent scraping.

import asyncio
from curl_cffi.requests import AsyncSession

async def scrape_urls(urls):
    async with AsyncSession(impersonate="chrome136") as session:
        tasks = [session.get(url) for url in urls]
        responses = await asyncio.gather(*tasks)
        return responses

urls = [
    "https://example.com/page/1",
    "https://example.com/page/2",
    "https://example.com/page/3"
]

results = asyncio.run(scrape_urls(urls))
for r in results:
    print(r.status_code)

Combining with Proxies

from curl_cffi import requests

proxies = {
    "http": "http://user:pass@proxy.example.com:8080",
    "https": "http://user:pass@proxy.example.com:8080"
}

response = requests.get(
    "https://protected-site.com",
    impersonate="chrome136",
    proxies=proxies,
    timeout=30
)

When to Use curl_cffi vs ScraperAPI

Use curl_cffi when:

  • You need HTTP-level speed (no browser overhead)
  • TLS fingerprinting is the primary detection method
  • You manage your own proxy infrastructure

Use ScraperAPI when:

  • The site also requires JavaScript rendering
  • You need managed proxy rotation
  • You want to avoid infrastructure maintenance

Verifying Your Fingerprint

from curl_cffi import requests

response = requests.get("https://tls.peet.ws/api/all", impersonate="chrome136")
fp = response.json()
print(f"JA3 hash: {fp['tls']['ja3_hash']}")
print(f"HTTP/2 fingerprint: {fp['http2']['akamai_fingerprint']}")

curl_cffi is the go-to library when you need fast, HTTP-level scraping that passes TLS fingerprint checks without the overhead of a full browser.