Client Hints & Browser Fingerprints¶
Gakido includes comprehensive support for Sec-CH-UA client hints and Canvas/WebGL fingerprint data for better browser impersonation.
Sec-CH-UA Client Hints¶
Client hints are HTTP headers that provide information about the browser and platform. Modern browsers (Chrome, Edge) send these automatically, and anti-bot systems check for their presence and consistency.
Automatic Client Hints¶
Chrome and Edge profiles automatically include basic client hints in requests:
from gakido import Client
# Client hints are sent automatically with Chrome/Edge profiles
with Client(impersonate="chrome_120") as c:
r = c.get("https://httpbin.org/headers")
print(r.json()["headers"])
# Includes: Sec-CH-UA, Sec-CH-UA-Mobile, Sec-CH-UA-Platform
Available Client Hints¶
| Header | Type | Description |
|---|---|---|
Sec-CH-UA |
Low entropy | Browser brand and version |
Sec-CH-UA-Mobile |
Low entropy | Mobile device indicator (?0 or ?1) |
Sec-CH-UA-Platform |
Low entropy | Operating system name |
Sec-CH-UA-Platform-Version |
High entropy | OS version |
Sec-CH-UA-Full-Version-List |
High entropy | Full browser version |
Sec-CH-UA-Arch |
High entropy | CPU architecture |
Sec-CH-UA-Bitness |
High entropy | CPU bitness (32/64) |
Sec-CH-UA-Model |
High entropy | Device model (mobile) |
Extracting Client Hints from Profiles¶
from gakido.impersonation import get_profile, get_client_hints_headers
profile = get_profile("chrome_120")
# Get basic hints (always sent)
basic = get_client_hints_headers(profile, include_high_entropy=False)
# {'Sec-CH-UA': '"Not_A Brand";v="8", ...', 'Sec-CH-UA-Mobile': '?0', ...}
# Get all hints including high-entropy
all_hints = get_client_hints_headers(profile, include_high_entropy=True)
# Includes: Sec-CH-UA-Platform-Version, Sec-CH-UA-Arch, etc.
Building Custom Client Hints¶
from gakido.impersonation import build_client_hints_for_platform
# Build hints for a custom platform
hints = build_client_hints_for_platform(
browser="Google Chrome",
version="120",
platform="Windows",
mobile=False,
platform_version="10.0.0",
arch="x86",
bitness="64",
)
Handling Accept-CH Response Headers¶
Servers can request additional client hints via the Accept-CH response header:
from gakido.impersonation import parse_accept_ch, get_profile
# Parse server's Accept-CH header
accept_ch = "Sec-CH-UA-Platform-Version, Sec-CH-UA-Arch"
requested = parse_accept_ch(accept_ch)
# ['Sec-CH-UA-Platform-Version', 'Sec-CH-UA-Arch']
# Get hints to send in next request
profile = get_profile("chrome_120")
hints = profile.get("client_hints", {})
for name in requested:
if name in hints:
print(f"{name}: {hints[name]}")
Canvas/WebGL Fingerprints¶
Canvas and WebGL fingerprints are used by anti-bot systems to identify browsers. Each profile includes realistic fingerprint data.
Accessing Fingerprint Data¶
from gakido.impersonation import get_profile, get_canvas_webgl_fingerprint
profile = get_profile("chrome_120")
fp = get_canvas_webgl_fingerprint(profile)
print(fp["webgl_vendor"]) # "Google Inc. (Apple)"
print(fp["webgl_renderer"]) # "ANGLE (Apple, ANGLE Metal Renderer: ...)"
print(fp["canvas_hash"]) # Unique canvas hash
Platform-Specific Fingerprints¶
Different profiles have appropriate fingerprints for their platform:
| Profile | WebGL Vendor | WebGL Renderer |
|---|---|---|
chrome_120 (macOS) |
Google Inc. (Apple) | ANGLE Metal Renderer: Apple M1 |
chrome_120_android |
Qualcomm | Adreno (TM) 730 |
edge_101 (Windows) |
Google Inc. (NVIDIA) | ANGLE NVIDIA GeForce RTX 3080 |
safari_170 |
Apple Inc. | Apple GPU |
firefox_133 |
Google Inc. (Apple) | ANGLE Metal Renderer |
tor_145 |
Mozilla | Mozilla |
Predefined WebGL Renderers¶
from gakido.impersonation import WEBGL_RENDERERS, get_webgl_renderer
# Available presets
print(WEBGL_RENDERERS.keys())
# chrome_macos_m1, chrome_macos_intel, chrome_windows_nvidia,
# chrome_windows_amd, chrome_android_adreno, chrome_android_mali,
# firefox_macos, safari_macos, safari_ios, tor
# Get specific renderer
renderer = get_webgl_renderer("chrome_windows_nvidia")
print(renderer["vendor"]) # "Google Inc. (NVIDIA)"
print(renderer["renderer"]) # "ANGLE (NVIDIA, NVIDIA GeForce RTX 3080 ...)"
Profile Client Hints Support¶
| Profile | Client Hints | Canvas/WebGL |
|---|---|---|
chrome_120 |
✅ Full | ✅ |
chrome_120_android |
✅ Full | ✅ |
edge_101 |
✅ Full | ✅ |
safari_170 |
❌ (Safari doesn't send) | ✅ |
safari_170_ios |
❌ | ✅ |
firefox_133 |
❌ (Firefox doesn't send) | ✅ |
tor_145 |
❌ | ✅ (uniform) |
API Reference¶
Functions¶
from gakido.impersonation import (
# Client hints
generate_sec_ch_ua, # Generate Sec-CH-UA header value
generate_sec_ch_ua_full_version_list, # Generate full version list
get_client_hints_headers, # Extract hints from profile
build_client_hints_for_platform, # Build custom hints
parse_accept_ch, # Parse Accept-CH header
should_send_hint, # Check if hint should be sent
# Canvas/WebGL
get_canvas_webgl_fingerprint, # Get fingerprint from profile
get_webgl_renderer, # Get predefined renderer
WEBGL_RENDERERS, # Dict of renderer presets
)
generate_sec_ch_ua¶
def generate_sec_ch_ua(
browser: str, # Browser name (e.g., "Google Chrome")
version: str, # Major version (e.g., "120")
chromium_version: str | None = None, # Chromium version if different
) -> str
get_client_hints_headers¶
def get_client_hints_headers(
profile: dict, # Browser profile
include_high_entropy: bool = False, # Include high-entropy hints
) -> dict[str, str]
get_canvas_webgl_fingerprint¶
def get_canvas_webgl_fingerprint(
profile: dict, # Browser profile
) -> dict[str, str] # Returns {webgl_vendor, webgl_renderer, canvas_hash}
Example: Full Impersonation¶
from gakido import Client
from gakido.impersonation import (
get_profile,
get_client_hints_headers,
get_canvas_webgl_fingerprint,
)
# Create client with Chrome impersonation
client = Client(impersonate="chrome_120")
profile = get_profile("chrome_120")
# View what's being sent
print("TLS:", len(profile["tls"]["ciphers"]), "chars cipher string")
print("HTTP/2:", list(profile["http2"]["settings"].keys()))
print("Client Hints:", list(get_client_hints_headers(profile, True).keys()))
print("WebGL:", get_canvas_webgl_fingerprint(profile)["webgl_renderer"])
# Make request with full impersonation
response = client.get("https://example.com")
client.close()