Pure-Python solver for the ServicePipe anti-bot: arm a session (PoW + signed fingerprint) and solve the rotate-captcha, no browser in the request path.
Project description
servicepipe-solver
Pure-Python library for the ServicePipe anti-bot (servicepipe.ru) used by various sites.
Given a URL it arms a session (cookies) the site accepts, solving both challenge paths — no browser,
no JS engine in the request path.
- Flow A — computational arming (the common path): compute the
spscproof-of-work + the signed browser-fingerprint cookiespjs, reload → real page.wasmtimeruns the extracted challenge WASM. - Flow B — rotate-captcha («Разверните картинку горизонтально»): a local RotNetR model predicts the upright angle, the drag telemetry is synthesized, signed, and blessed.
Install (uv)
uv add servicepipe-solver # core: flow A (wreq + wasmtime)
uv add "servicepipe-solver[captcha]" # + flow B (torch RotNetR; model downloaded on first use)
uv add "servicepipe-solver[scrapy]" # + the Scrapy integration (contrib.scrapy)
Python ≥3.11. The base install is light; torch/torchvision come only with [captcha].
Use
import asyncio
from servicepipe_solver import solve
res = asyncio.run(solve("https://example.com/", allow_captcha=True))
# res.ok, res.flow (armed_a / captcha_b / open / forbidden / version_mismatch / failed)
# res.cookies -> {spsc, spid, spjs, ...} attach to every request to that origin
# res.client -> the armed wreq client (its cookie store) for reuse
if res.ok:
page = await res.client.get(product_url, cookies=res.cookies)
The armed session = the cookie dict. Attach res.cookies to every subsequent request to that
origin (ServicePipe cookies are set by JS, not Set-Cookie); the session persists (one arm → many
real pages).
Bring your own transport / proxy
The solver depends only on the Transport protocol; the default WreqTransport emulates Chrome's
TLS/HTTP2 fingerprint. Inject a pre-built client (e.g. with a proxy) or your own transport:
import wreq
from servicepipe_solver import solve
client = wreq.Client(emulation=..., proxy="http://user:pass@host", cookie_store=True)
res = await solve(url, client=client) # arming goes through YOUR client; reuse it for the crawl
Any transport you inject MUST present a real Chrome TLS/HTTP2 fingerprint. ServicePipe blocks a plain-Python TLS handshake regardless of correct cookies — this is why the default uses
wreq.
Low-level engine (transport-free primitives)
If you already have a Chrome-fingerprinted transport (or a browser) and want to drive the protocol
yourself, servicepipe_solver.engine exposes the pure, no-networking primitives:
from servicepipe_solver.engine import parse_inline, spsc, SpjsBuilder, CheckjsRuntime
ch = parse_inline(inline_script) # you fetched the page yourself
sc = spsc(checkjs_text, ch.options)
spjs, _ = SpjsBuilder(CheckjsRuntime.load()).build(origin, ch.spid_cookie, sc)
Scrapy
servicepipe_solver.contrib.scrapy (extra [scrapy]) ships two integration paths:
ServicePipeMiddleware— a drop-in downloader middleware: arms out-of-band on a challenge and reissues the request with the armed cookies.ScrapyTransport— runs the arming loop through the crawler's downloader (inherits its middlewares/proxy/throttle).
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file servicepipe_solver-0.1.0.tar.gz.
File metadata
- Download URL: servicepipe_solver-0.1.0.tar.gz
- Upload date:
- Size: 60.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
23e0981aa72f9fe94f981aa46cc4ed0ae316c4112d5c11929ebc09979fd52665
|
|
| MD5 |
23f4ebad5bbc219f130efbee42426e07
|
|
| BLAKE2b-256 |
f3555bdbd21ec59168fec3e6c9d154ceb2f8dd963e7c8163e8b639ce43cf1d04
|
Provenance
The following attestation bundles were made for servicepipe_solver-0.1.0.tar.gz:
Publisher:
release.yml on alexpervushin/servicepipe-solver
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
servicepipe_solver-0.1.0.tar.gz -
Subject digest:
23e0981aa72f9fe94f981aa46cc4ed0ae316c4112d5c11929ebc09979fd52665 - Sigstore transparency entry: 2050324074
- Sigstore integration time:
-
Permalink:
alexpervushin/servicepipe-solver@463501f6f8df4c1d8456bfa2fc97224e425e93a1 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/alexpervushin
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@463501f6f8df4c1d8456bfa2fc97224e425e93a1 -
Trigger Event:
push
-
Statement type:
File details
Details for the file servicepipe_solver-0.1.0-py3-none-any.whl.
File metadata
- Download URL: servicepipe_solver-0.1.0-py3-none-any.whl
- Upload date:
- Size: 92.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5d78c4163b8a77d6bc8850455e47c8e59a80d0bc72bac6ede3216c5c6aa575e7
|
|
| MD5 |
3787de7d98cd74256a3308aa591a9393
|
|
| BLAKE2b-256 |
e0b31dcddf0fbd7cfae127989a24bf22d0456c1bec3afb59d0011fe204949c75
|
Provenance
The following attestation bundles were made for servicepipe_solver-0.1.0-py3-none-any.whl:
Publisher:
release.yml on alexpervushin/servicepipe-solver
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
servicepipe_solver-0.1.0-py3-none-any.whl -
Subject digest:
5d78c4163b8a77d6bc8850455e47c8e59a80d0bc72bac6ede3216c5c6aa575e7 - Sigstore transparency entry: 2050324318
- Sigstore integration time:
-
Permalink:
alexpervushin/servicepipe-solver@463501f6f8df4c1d8456bfa2fc97224e425e93a1 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/alexpervushin
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@463501f6f8df4c1d8456bfa2fc97224e425e93a1 -
Trigger Event:
push
-
Statement type: