Skip to content

Custom JA3 Impersonate issue with curl_cffi version 0.16.0b2 #815

Description

@charliedelta02

Please check the following items and answer all the questions when reporting a bug,
otherwise it will be closed immediately.

  • [ x] I'm not asking you to help bypass a specific site with curl_cffi.
  • [ x] A code snippet that can reproduce this bug will be provided, even if it's a one-liner.
  • [ x] Version and environment information will be pasted as below.
  • A curl-cffi doctor output will be included.

Describe the bug
The firefox FP for version 152 has changed as opposed to forefox147 impersonate support which is the latest available on curl_cffi.
As a consequence, I used the custom fingerprint approach to mimic the fingerprint for firefox v152 (code snippet attached).
The custom impersonate changes works fine with cffi pre-release version 0.16.0b1 whereas it fails with version 0.16.0b2.

The expected firefox v152 fingerprint (same behavior observed with v0.16.0b1):

{
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:152.0) Gecko/20100101 Firefox/152.0",
  "ja4": "t13d1617h2_86a278354501_3cbfd9057e0d",
  "ja4_r": "t13d1617h2_002f,0035,009c,009d,1301,1302,1303,c00a,c013,c014,c02b,c02c,c02f,c030,cca8,cca9_0005,000a,000b,000d,0012,0017,001b,001c,0022,0023,002b,002d,0033,fe0d,ff01_0403,0503,0603,0804,0805,0806,0401,0501,0601,0203,0201",
  "ja4_o": "t13d1617h2_d6294ab6b85e_df135d36b6d5",
  "ja4_ro": "t13d1617h2_1301,1303,1302,c02b,c02f,cca9,cca8,c02c,c030,c00a,c013,c014,009c,009d,002f,0035_0000,0017,ff01,000a,000b,0023,0010,0005,0022,0012,0033,002b,000d,002d,001c,001b,fe0d_0403,0503,0603,0804,0805,0806,0401,0501,0601,0203,0201",
  "ja3_hash": "6447ab086255d194909d4013b1a89e87",
  "ja3_text": "771,4865-4867-4866-49195-49199-52393-52392-49196-49200-49162-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",
  "ja3n_hash": "8099457c290ccfe8c6d958826c26b023",
  "ja3n_text": "771,4865-4867-4866-49195-49199-52393-52392-49196-49200-49162-49171-49172-156-157-47-53,0-5-10-11-13-16-18-23-27-28-34-35-43-45-51-65037-65281,4588-29-23-24-25-256-257,0",
  "akamai_hash": "6ea73faa8fc5aac76bded7bd238f6433",
  "akamai_text": "1:65536;2:0;4:131072;5:16384|12517377|0|m,p,a,s"
}

The behavior observed on v0.16.0b2:

{
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:152.0) Gecko/20100101 Firefox/152.0",
  "ja4": "t13d1614h2_86a278354501_2fac7b6afcb3",
  "ja4_r": "t13d1614h2_002f,0035,009c,009d,1301,1302,1303,c00a,c013,c014,c02b,c02c,c02f,c030,cca8,cca9_000a,000b,000d,0017,001b,001c,0022,0023,002b,002d,0033,ff01_0403,0503,0603,0804,0805,0806,0401,0501,0601,0203,0201",
  "ja4_o": "t13d1614h2_d6294ab6b85e_1015e1646692",
  "ja4_ro": "t13d1614h2_1301,1303,1302,c02b,c02f,cca9,cca8,c02c,c030,c00a,c013,c014,009c,009d,002f,0035_0000,0017,ff01,000a,000b,0023,0010,0022,0033,002b,000d,002d,001c,001b_0403,0503,0603,0804,0805,0806,0401,0501,0601,0203,0201",
  "ja3_hash": "927727f2bad89b49b561660c8ae81603",
  "ja3_text": "771,4865-4867-4866-49195-49199-52393-52392-49196-49200-49162-49171-49172-156-157-47-53,0-23-65281-10-11-35-16-34-51-43-13-45-28-27,4588-29-23-24-25-256-257,0",
  "ja3n_hash": "028617ac9e1e691c3e9b9908e1194cbc",
  "ja3n_text": "771,4865-4867-4866-49195-49199-52393-52392-49196-49200-49162-49171-49172-156-157-47-53,0-10-11-13-16-23-27-28-34-35-43-45-51-65281,4588-29-23-24-25-256-257,0",
  "akamai_hash": "6ea73faa8fc5aac76bded7bd238f6433",
  "akamai_text": "1:65536;2:0;4:131072;5:16384|12517377|0|m,p,a,s"
}

To Reproduce
Run this script on v0.16.0b2 and v0.16.0b1.

import json
from curl_cffi.requests import Session

# Firefox 152: removed cipher 49161 (TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA) vs v147
ja3 = "771,4865-4867-4866-49195-49199-52393-52392-49196-49200-49162-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"

akamai = "1:65536;2:0;4:131072;5:16384|12517377|0|m,p,a,s"

extra_fp = {
    "tls_signature_algorithms": [
        "ecdsa_secp256r1_sha256",
        "ecdsa_secp384r1_sha384",
        "ecdsa_secp521r1_sha512",
        "rsa_pss_rsae_sha256",
        "rsa_pss_rsae_sha384",
        "rsa_pss_rsae_sha512",
        "rsa_pkcs1_sha256",
        "rsa_pkcs1_sha384",
        "rsa_pkcs1_sha512",
        "ecdsa_sha1",
        "rsa_pkcs1_sha1",
    ],
    "tls_delegated_credential": "ecdsa_secp256r1_sha256:ecdsa_secp384r1_sha384:ecdsa_secp521r1_sha512:ecdsa_sha1",
    "tls_record_size_limit": 4001,
    "tls_cert_compression": "zlib",
    "tls_grease": False,
    "tls_permute_extensions": False,
    "http2_stream_weight": 42,
    "http2_stream_exclusive": 0,
}

headers = {
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:152.0) Gecko/20100101 Firefox/152.0",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.5",
    "Accept-Encoding": "gzip, deflate, br, zstd",
    "Connection": "keep-alive",
    "Upgrade-Insecure-Requests": "1",
    "Sec-Fetch-Dest": "document",
    "Sec-Fetch-Mode": "navigate",
    "Sec-Fetch-Site": "none",
    "Sec-Fetch-User": "?1",
    "Priority": "u=0, i",
}

TARGET_JA3_HASH = "6447ab086255d194909d4013b1a89e87"
TARGET_AKAMAI_HASH = "6ea73faa8fc5aac76bded7bd238f6433"

if __name__ == "__main__":
    with Session() as s:
        r = s.get(
            "https://tls.browserleaks.com/json",
            ja3=ja3,
            akamai=akamai,
            extra_fp=extra_fp,
            headers=headers,
        )

        data = r.json()
        print(json.dumps(data, indent=2))

        print("\n--- Fingerprint Comparison ---")
        print(f"JA3 hash:    {data.get('ja3_hash', 'N/A')}")
        print(f"Expected:    {TARGET_JA3_HASH}")
        print(f"Match:       {'YES' if data.get('ja3_hash') == TARGET_JA3_HASH else 'NO'}")
        print()
        print(f"Akamai hash: {data.get('akamai_hash', 'N/A')}")
        print(f"Expected:    {TARGET_AKAMAI_HASH}")
        print(f"Match:       {'YES' if data.get('akamai_hash') == TARGET_AKAMAI_HASH else 'NO'}")

Expected behavior
When we are using the right custom impersonate fingerprint (bringing our own fingerprint) the generated fingerprint by curl_cffi must match the expected fingerprint.
v0.16.0b1 works as expected where as v0.16.0b2 does not.

Versions

  • OS: [linux x64, macOS Sequoia ]
  • curl_cffi version [v0.16.0b2, v0.16.0b1]
  • pip freeze dump
python: 3.12.6 (v3.12.6:a4a2d2b0d85) [Clang 13.0.0 (clang-1300.0.29.30)]
platform: macOS-26.5.2-arm64-arm-64bit arm64
curl_cffi: 0.16.0b2

Additional context

  • Which session are you using? async or sync? Async and Sync
  • If using async session, which loop implementation are you using? NA
  • If you have tried, does this work with other http clients, e.g. requests, httpx or real browsers --> Have not verified

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions