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 148 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.4.tar.gz (24.6 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.4-py3-none-any.whl (29.2 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: shardx-0.1.4.tar.gz
  • Upload date:
  • Size: 24.6 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.4.tar.gz
Algorithm Hash digest
SHA256 94a6ed6f636fab9711f6106e5a3e0314850d71c1b29d9f710c91e027763a12c6
MD5 82a98f62bf90d4d1758c2f24147e0a9c
BLAKE2b-256 9e4030224d74772f80b0825c5d52d4033041bfd6e38af5f48fc81f607b53f617

See more details on using hashes here.

File details

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

File metadata

  • Download URL: shardx-0.1.4-py3-none-any.whl
  • Upload date:
  • Size: 29.2 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.4-py3-none-any.whl
Algorithm Hash digest
SHA256 8c099cd51c21e78eb1ae40fc5eeec2842abf49dcb2ee960fe7e25fb62830caae
MD5 2e05dbca2d6ca24cac047f1a373e01b4
BLAKE2b-256 70e1d98ecc6276c373ceef128ff4d762977f8dfe1cae0721d6f646269cdb3dce

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