Skip to main content

Self-contained Python SDK for the ShardX anti-detect browser — downloads the engine + Widevine + fingerprint library on first use, launches isolated profiles.

Project description

shardx (Python)

Self-contained Python SDK for the ShardX anti-detect browser by the ProxyShard team.

This package does not depend on the desktop launcher. On first use it downloads the patched Chromium 149 engine, Widevine CDM, and the 170-profile fingerprint library from our CDN into a local cache, then launches isolated browser sessions on demand.

Driven by patchright (stealth-patched Playwright) — sdk.session() returns a ready-to-use Browser instance, no manual connect_over_cdp plumbing.

Install

pip install shardx

Supported hosts: macOS arm64, Windows x64, Linux x64.

Linux system dependencies

The bundled Chromium engine needs unzip + the standard set of shared libraries any Chromium fork links against. On a fresh Debian / Ubuntu:

sudo apt install -y \
  unzip ca-certificates fonts-liberation \
  libnss3 libnspr4 libatk1.0-0 libatk-bridge2.0-0 libcups2 \
  libxkbcommon0 libxcomposite1 libxdamage1 libxfixes3 libxrandr2 \
  libgbm1 libpango-1.0-0 libcairo2 libasound2 libxshmfence1

When launching as root or inside Docker, pass --no-sandbox and --disable-dev-shm-usage via extra_args=:

await sdk.session(..., extra_args=["--no-sandbox", "--disable-dev-shm-usage"])

Quick start

import asyncio
from shardx import ShardX

async def main():
    sdk = ShardX()
    # Engine + Widevine + fingerprint library auto-download from CDN on
    # the first `session`/`launch`/`list_profiles` call (~170 MB once,
    # etag-cached afterward).  No separate install step.

    # Launch + drive in one call. Yields a patchright `Browser`.
    async with sdk.session("win-rtx4060", proxy="socks5://user:pass@host:port") as browser:
        ctx = browser.contexts[0]
        page = await ctx.new_page()
        await page.goto("https://browserleaks.com/quic")
        print(await page.title())

        # Inspect what the SDK resolved before launch:
        sess = browser._shardx
        print(sess.geo)                   # GeoInfo(...) from ip-api / ipapi.co
        print(sess.proxy_udp_ms,          # UDP RTT in ms or None
              sess.quic_enabled,          # bool
              sess.webrtc_mode)           # "auto" | "tcp_only" | "block"
    # browser + udd shut down cleanly on exit

asyncio.run(main())

Random profile when none specified

async with sdk.session(platform="Windows", randomize=True) as browser:
    # picks a random win-* profile, re-randomises hardware_concurrency /
    # device_memory / platform_version using the host as a basis
    page = await browser.contexts[0].new_page()
    ...

Discover bundled profiles

print(sdk.list_profiles()[:5])
# ['linux-gt1030', 'linux-gtx1050', 'mac-m1-air13', 'mac-m1-imac24', 'mac-m1-max-mbp14']

print(sdk.list_profiles(platform="Windows")[:5])

profile = sdk.random_profile(platform="macOS")
print(profile.id, profile.config["webgl"]["renderer"])

Validate a proxy before binding

print(sdk.check_proxy("socks5://user:pass@host:port"))
# {
#   'udp_ms': 142.3,
#   'geo': GeoInfo(country_code='DE', timezone='Europe/Berlin', ...),
#   'would_enable_quic': True,
#   'would_set_webrtc': 'auto',
# }

Pre-launch checks

Every call to sdk.session() / sdk.launch() runs the same pre-spawn pipeline the desktop launcher uses:

  1. resolve_auto_fields — if the profile has "auto" sentinels for timezone, navigator.language, or geolocation.mode, the SDK makes a live geo lookup through the bound proxy (ip-api.com by default). It then writes concrete values: timezone (from the API, never a static table), accept_language chain, languages, icu_locale (always overwritten so Intl.* matches navigator.language), and lat/lng. Proxy-via failure → direct geo → host $LANG / $TZ as last-resort fallback. The chosen geo is surfaced on session.geo.
  2. apply_screen_strategy — see below.
  3. probe_udp — SOCKS5 UDP_ASSOCIATE round-trip. If it fails, QUIC is force-disabled and WebRTC switches to tcp_only automatically.

Screen strategy

screen_mode kw to session() / launch():

  • "profile" — keep whatever the fingerprint claims.
  • "cap_to_host"macOS default. If the host monitor is smaller than the FP screen, scale screen.* + window.* down proportionally; otherwise no-op.
  • "use_host"Windows/Linux default. Overwrite screen.* with the real monitor (minus a 40 px Windows taskbar) and recompute window.outer_* / window.inner_* accordingly.

Default mode is picked from navigator.platform. Override per launch:

async with sdk.session("win-rtx4060", screen_mode="profile") as browser:
    ...

Host-aware hardware randomisation

randomize=True re-picks hardware_concurrency, device_memory, and platform_version before the launch — using the same logic as the desktop launcher (randomize_hardware in lib.rs):

  • macOS profiles use the curated MAC_HW_CONFIGS table by id.
  • Windows / Linux profiles bracket the host's logical CPU count within [host − 4, host + 2] from the real x86 set [4, 6, 8, 12, 16, 20, 24, 28, 32]; device_memory is floored by core count (≥ 12 → 16, else 8) and capped by host_ram_bucket_gb() (8 / 16 / 32 GiB bucketed from sysctl hw.memsize / /proc/meminfo / Get-CimInstance Win32_ComputerSystem).

So a profile launched on an 8-core / 16 GB laptop will never claim 32 cores / 128 GB of RAM — keeps fingerprints internally consistent with real-world hardware.

Override fingerprint fields

profile = sdk.library.load("win-rtx4060").with_override(
    name="my-account",
    timezone="Europe/Berlin",
    navigator={"language": "de-DE"},
)
async with sdk.session(profile, proxy="socks5://...") as browser:
    ...

Use your own fingerprint JSON

from shardx import Profile

profile = Profile.from_file("/path/to/my-custom.json")
async with sdk.session(profile) as browser:
    ...

WebRTC policy

async with sdk.session(
    "win-rtx4060",
    proxy="socks5://...",
    webrtc="tcp_only",                # or "block" | "auto" (default)
    webrtc_public_ip="203.0.113.42",  # advertised in ICE candidates
) as browser:
    ...

Advanced: raw launch without patchright

If you'd rather drive the browser with a different CDP client (raw pychrome, pyppeteer, your own WebSocket), skip session() and use launch() directly:

sess = sdk.launch("win-rtx4060", proxy="socks5://...", cdp=True)
print(sess.cdp_url)        # ws://127.0.0.1:54113/devtools/browser/c0a3…
# … drive it yourself …
sess.stop()

launch() does the same pre-launch pipeline (auto-resolve, screen strategy, UDP probe, hw randomisation) and returns a BrowserSession with cdp_url, geo, proxy_udp_ms, quic_enabled, webrtc_mode, user_data_dir, and stop().

Cache layout

~/Library/Application Support/shardx-sdk/    (mac)
%LOCALAPPDATA%\shardx-sdk\                   (win)
~/.cache/shardx-sdk/                         (linux)
├── manifest.json             ← etag cache for browser/widevine/fingerprints
├── ShardX-Mac-arm64/         ← extracted engine
│   └── ShardX.app/…
├── fingerprints/             ← 170 bundled .json profiles
│   ├── win-rtx4060.json
│   └── …
└── profiles/                 ← per-launch user-data-dir (cookies, IndexedDB, cache)
    └── <profile-id>/

Override the cache root:

sdk = ShardX(cache_dir="/data/shardx")

Update the runtime

The SDK auto-checks remote etags on the first session/launch/list_profiles call of each process and re-downloads anything that changed. To force a re-download mid-process (e.g. CI scenarios):

sdk.runtime.install(force=True)

License

MIT (this SDK). The Chromium-fork engine binary downloaded at runtime is a closed-source product — see the main repo for engine licensing.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

shardx-0.1.8.tar.gz (26.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

shardx-0.1.8-py3-none-any.whl (31.1 kB view details)

Uploaded Python 3

File details

Details for the file shardx-0.1.8.tar.gz.

File metadata

  • Download URL: shardx-0.1.8.tar.gz
  • Upload date:
  • Size: 26.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.4

File hashes

Hashes for shardx-0.1.8.tar.gz
Algorithm Hash digest
SHA256 e2c3ec322fbdcaca1f34fd2290eeff1e9fe4101869a818fef3e92718dc6f1b69
MD5 584b8b18b6d80c3437f8faf46151bbd8
BLAKE2b-256 fb623cd3f8c9b7a7d3365109fe92f54b020582fa9dff5b8ae3dc2e3369f7620f

See more details on using hashes here.

File details

Details for the file shardx-0.1.8-py3-none-any.whl.

File metadata

  • Download URL: shardx-0.1.8-py3-none-any.whl
  • Upload date:
  • Size: 31.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.4

File hashes

Hashes for shardx-0.1.8-py3-none-any.whl
Algorithm Hash digest
SHA256 9dd865b648efdfd88ba9df232b890bb921bd52f530034f2f4e78d197530bff82
MD5 2b3a8ceb5fb93d1f74ed42a9680dca74
BLAKE2b-256 7457d79e1e9ef72f14495325d8fb6902cd061269eebedb537ee2a9a1af38634c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page