بازگشت به وبلاگ

چگونه در سال ۲۰۲۶ از فینگرپرینتینگ TLS/JA4 عبور کنیم: curl_cffi و شبیه‌سازی مرورگر در عمل

رزیدنت پروکسی خریدید، اما سایت هنوز هم در درخواست اول ۴۰۳ می‌دهد؟ شما را از طریق TLS handshake قبل از HTTP headers شناسایی می‌کنند. بررسی می‌کنیم که چگونه می‌توان با JA3/JA4 fingerprinting مقابله کرد و در پنج دقیقه از طریق curl_cffi و شبیه‌سازی مرورگر آن را دور زد — با کد، بررسی اثر انگشت و انتخاب پروکسی.

📅۳۰ تیر ۱۴۰۵
چگونه در سال ۲۰۲۶ از فینگرپرینتینگ TLS/JA4 عبور کنیم: curl_cffi و شبیه‌سازی مرورگر در عمل

شما پروکسی‌های مقیم خریداری کرده‌اید، یک User-Agent جدید Chrome تنظیم کرده‌اید، اما سایت در اولین درخواست 403 را نمایش می‌دهد. آیا این برای شما آشناست؟ مشکل نه در IP و نه در هدرهاست. شما قبل از اینکه سرور حتی یک HTTP-header را بخواند شناسایی شده‌اید — به دلیل دست دادن TLS. در سال 2026 این وکتور شناسایی شماره 1 است و درخواست‌های معمولی requests به‌طور خودکار آن را رد می‌کنند. بیایید بررسی کنیم که این چگونه کار می‌کند و چگونه می‌توان آن را با چند خط کد از طریق curl_cffi تعمیر کرد.

چه اتفاقی می‌افتد: شما توسط دست دادن TLS شناسایی می‌شوید

زمانی که مشتری یک اتصال HTTPS برقرار می‌کند، ابتدا بسته ClientHello را ارسال می‌کند — حتی قبل از هرگونه HTTP. در آن، نسخه TLS، لیست مجموعه‌های رمزنگاری پشتیبانی شده (cipher suites)، گسترش‌های TLS (SNI، ALPN، supported_groups)، منحنی‌های بیضوی و فرمت‌های نقاط ذکر شده است. ترتیب و ترکیب این فیلدها در مشتریان مختلف متفاوت است — و بر اساس آن می‌توان مشتری را قبل از اینکه حتی یک کلمه بگوید شناسایی کرد.

از این فیلدها یک اثر انگشت محاسبه می‌شود. JA3 (استاندارد سال 2017) رشته‌ای از نوع TLSVersion,Ciphers,Extensions,EllipticCurves,ECPointFormats را می‌گیرد و آن را با MD5 هش می‌کند و یک امضای 32 کاراکتری به دست می‌آورد. مشکل JA3 این است که از ژانویه 2023 Chrome ترتیب گسترش‌ها را تصادفی می‌کند — 16 گسترش 16! (بیش از 20 تریلیون) گزینه می‌دهد و یک مرورگر یکسان امضای JA3‌های متفاوتی تولید می‌کند.

به همین دلیل صنعت به JA4 (FoxIO، پیاده‌سازی انبوه 2024–2025) منتقل شده است. JA4 کدهای گسترش را قبل از هش کردن بر اساس مقدار hex مرتب می‌کند — تصادفی‌سازی Chrome دیگر آن را خراب نمی‌کند. هش — SHA-256 کوتاه شده است، فرمت آن قابل خواندن و سه‌قسمتی (a_b_c) است، که شامل ALPN و پشتیبانی از QUIC/HTTP3 می‌باشد. مثال: Chrome 124 t13d1516h2 را می‌دهد (15 رمز، 16 گسترش، ALPN h2)، در حالی که Python خالص requestst13d1715h2 را تولید می‌کند. برای ضد ربات، امضای دوم یک نشانگر مستقیم «این یک اسکریپت است» است.

چرا در سال 2026 بدون این نمی‌توان پیش رفت

شناسایی JA4 در تمام فروشندگان بزرگ گنجانده شده است: Cloudflare اثر انگشت را با allowlist‌ها مقایسه می‌کند، Akamai یک هش جداگانه برای فریم‌های HTTP/2 SETTINGS اضافه می‌کند، DataDome آن را با پایگاه داده ربات‌های شناخته شده مقایسه می‌کند. منطق ساده و کشنده است: اگر شما User-Agent: Chrome 131 ارسال کنید و اثر انگشت TLS فریاد بزند «urllib3/OpenSSL» — این عدم همزمانی است و شما به سرعت مسدود می‌شوید. هیچ پروکسی‌ای نجات‌دهنده نیست: یک IP مقیم ایده‌آل با اثر انگشت Python requests همچنان شکست می‌خورد.

به همین دلیل است که ترکیب «پروکسی + جعل اثر انگشت» در سال 2026 به بهداشت پایه‌ای اسکرپینگ تبدیل شده است، نه یک گزینه برای پیشرفته‌ها.

راه‌حل: curl_cffi در 5 دقیقه

curl_cffi یک پوشش Python بر روی curl-impersonate (curl تغییر یافته، ساخته شده با BoringSSL از Chrome یا NSS از Firefox به جای OpenSSL) است. این یک دست دادن واقعی مرورگر را شبیه‌سازی می‌کند و در عین حال API‌ای تقریباً مشابه requests عادی دارد.

مرحله 1. نصب. باینری‌های curl-impersonate به‌طور خودکار برای Windows/macOS/Linux بارگذاری می‌شوند:

pip install curl-cffi

مرحله 2. درخواست پایه. واردات را تغییر داده و یک پارامتر اضافه کنید:

from curl_cffi import requests

resp = requests.get("https://target.com/", impersonate="chrome")
print(resp.status_code)
print(resp.http_version)  # HTTP/2 — مانند یک مرورگر واقعی

یک خط impersonate="chrome" به‌طور همزمان چهار لایه را جعل می‌کند: اثر انگشت TLS (JA3/JA4)، نسخه HTTP (HTTP/2 به جای HTTP/1.1)، ترتیب هدرها و مذاکره‌های ALPN.

مرحله 3. همیشه از generic-alias استفاده کنید، نه از نسخه پین شده. بنویسید impersonate="chrome" (یا "safari", "safari_ios") — alias به‌طور خودکار به جدیدترین پروفایل حل می‌شود. impersonate="chrome124" به زودی منقضی می‌شود: Chrome هر ~4 هفته به‌روز می‌شود و پروفایل قدیمی خود به خود به یک انحراف تبدیل می‌شود. اهداف قابل اعتماد — Chrome، Edge و Safari/iOS (پروفایل‌ها از chrome99 تا chrome131، safari15–18).

مرحله 4. پروکسی و جلسات. برای اسکرپینگ واقعی، وضعیت را در یک جلسه نگه دارید و پروکسی‌ها را متصل کنید. IP مقیم یا موبایل در اینجا الزامی است — دیتاسنتر به‌طور جداگانه از TLS شناسایی می‌شود:

from curl_cffi import requests

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

headers = {
    "Accept-Language": "en-US,en;q=0.9",
    "Accept-Encoding": "gzip, deflate, br",
    "Referer": "https://www.google.com/",
}
proxies = {
    "http": "http://user:pass@proxy-host:port",
    "https": "http://user:pass@proxy-host:port",
}

resp = session.get("https://target.com", headers=headers, proxies=proxies)

مرحله 5. ناهمزمانی برای حجم. بر خلاف requests، curl_cffi به‌طور پیش‌فرض دارای async و HTTP/2 است:

import asyncio
from curl_cffi.requests import AsyncSession

async def fetch(session, url):
    r = await session.get(url, impersonate="chrome")
    return r.status_code

async def main(urls):
    async with AsyncSession() as session:
        return await asyncio.gather(*[fetch(session, u) for u in urls])

asyncio.run(main(["https://target.com"] * 20))

اثر انگشت خود را بررسی کنید — حدس نزنید

قبل از اینکه ترافیک واقعی را ارسال کنید، مطمئن شوید که جعل واقعاً کار می‌کند. یک درخواست به تأییدکننده‌های عمومی ارسال کنید و JA4 را با اثر انگشت مرورگر مرجع مقایسه کنید:

  • tls.peet.ws — JA3، JA4، اثر انگشت Akamai و فریم‌های HTTP/2 را در JSON برمی‌گرداند. آن را از طریق curl_cffi و از طریق Chrome واقعی درخواست کنید و هش‌ها را مقایسه کنید.
  • ja4db.com — پایگاه داده JA4‌های شناخته شده، به درک اینکه به چه کسی شبیه هستید کمک می‌کند.
  • browserleaks.com/tls و ابزار JA3/JA4 از Scrapfly — تجزیه و تحلیل دقیق فیلدها.

در استیجینگ، راحت است که mitmproxy را بین اسکرپر و هدف قرار دهید و هش JA4 واقعی هر درخواست را نظارت کنید.

تشخیص: هنوز 403/429 را دریافت می‌کنید

اگر اثر انگشت صحیح است و مسدودسازی‌ها باقی مانده‌اند — به چک‌لیست از رایج به نادر بروید:

  1. IP دیتاسنتری. دلیل شماره 1. به پروکسی‌های مقیم یا موبایل بروید — چرا یک اثر انگشت کافی نیست، به تفصیل در مقاله‌ای درباره شناسایی پروکسی‌های مقیم از طریق IP Intelligence توضیح داده شده است.
  2. پروفایل منقضی. pip install -U curl-cffi و generic-alias "chrome".
  3. نرخ بسیار بالا. بین درخواست‌ها وقفه‌های تصادفی 1–3 ثانیه‌ای اضافه کنید.
  4. هدرهای خالی. حتماً Accept-Language، Accept-Encoding، Referer را ارسال کنید — عدم وجود آن‌ها نیز یک انحراف است.
  5. عدم همزمانی جلسه و IP. قاعده: یک جلسه — یک IP برای تمام مدت زمان آن.
  6. وضعیت 200 ≠ موفقیت. بدنه پاسخ را بررسی کنید: ممکن است صفحه‌ای با CAPTCHA زیر کد 200 باشد.

کجا curl_cffi به دیوار می‌خورد

curl_cffi لایه شبکه را می‌بندد — و همین. این JavaScript را اجرا نمی‌کند. بنابراین در برابر چالش‌های JS ناتوان است: Cloudflare Turnstile، صفحه «در حال بررسی مرورگر شما…» (IUAM)، کوکی cf_clearance که اسکریپت پس از بررسی قرار می‌دهد — همه این‌ها به یک محیط مرورگر واقعی نیاز دارند. چرا در سال 2026 حل‌کننده‌های CAPTCHA تقریباً در برابر چنین سیستم‌های پیشگیرانه کار نمی‌کنند، ما در یک بررسی جداگانه درباره دور زدن CAPTCHA بررسی کردیم.

چه کار کنید زمانی که به دیوار JS برخوردید:

  • هیبرید. Playwright یا Nodriver چالش را اجرا می‌کند و cf_clearance را دریافت می‌کند، سپس کوکی را به curl_cffi سریع برای اکثر درخواست‌ها منتقل می‌کند — بنابراین شما یک بار برای مرورگر سنگین هزینه می‌کنید.
  • سرویس‌های حل‌کننده (CapSolver، 2Captcha) برای ارائه خودکار توکن‌ها.
  • API اسکرپینگ مدیریت شده، اگر نمی‌خواهید زیرساخت را نگه دارید.

و به ایمنی رشته‌ها توجه کنید: هر رشته — جلسه خود را دارد. نسخه curl-cffi را در requirements.txt قفل کنید و پروفایل‌ها را هر 6–12 هفته یک بار بازبینی کنید، زمانی که مرورگرها به‌روز می‌شوند.

جایگزین‌های curl_cffi

  • tls-client — پوششی بر روی کتابخانه Go مبتنی بر uTLS، با پروفایل‌ها (chrome_124, safari_ios_17) و پرچم random_tls_extension_order=True. تنظیم دقیق انعطاف‌پذیر اثر انگشت.
  • primp — کلاینتی بر روی Rust، که اجازه می‌دهد impersonate_os را به‌طور مستقل تنظیم کنید و ظرفیت بالاتری را ارائه می‌دهد؛ معایب — API به‌طور کامل با requests مطابقت ندارد و این کتابخانه جوان‌تر است.

چه پروکسی لازم است و چرا

جعل اثر انگشت و پروکسی دو نیمه متفاوت از یک مسئله را حل می‌کنند: curl_cffi سؤال «اتصال چگونه به نظر می‌رسد» را می‌بندد، پروکسی — «از کجا می‌آید». ضد ربات به‌طور مستقل هر دو سیگنال را بررسی می‌کند، بنابراین JA4 ایده‌آل با ASN دیتاسنتر سیاه بی‌فایده است. برای اهداف حساس (بازارها، شبکه‌های اجتماعی، تجمیع‌کننده‌های سفر) پروکسی‌های مقیم یا موبایل بگیرید: آن‌ها منبع اپراتوری پاک دارند و پروکسی‌های موبایل همچنین پشت CGNAT «اثر جمعیت» پنهان می‌شوند. دیتاسنتر را برای اهداف غیر حساس و حجم بالا نگه دارید.

نتیجه‌گیری

در سال 2026، اسکرپینگ یک بازی هویت‌ها است، نه فقط IP. requests خالص به عنوان یک اسکریپت در سطح دست دادن TLS شناسایی می‌شود و قبل از اولین هدر شکست می‌خورد. جایگزینی واردات با curl_cffi و impersonate="chrome" این شکست را در پنج دقیقه برطرف می‌کند، اما تنها در ترکیب با IP مقیم یا موبایل پاک و با درک مرز: لایه شبکه — بله، چالش‌های JavaScript — نه. یک استک صادقانه جمع‌آوری کنید: اثر انگشت صحیح، پروکسی صحیح، هیبرید با مرورگر در جایی که دیوار JS وجود دارد — و 403 در اولین درخواست به گذشته خواهد پیوست.