An unofficial async Python client for the chat.deepseek.com web API. It reproduces the browser's request flow — including the proof-of-work (PoW) challenge that DeepSeek requires before every chat completion — and streams the model's response back as text.
The PoW challenge is solved by a small Keccak-256 brute-force solver written in Go, driven from Python via a subprocess wrapper that compiles the Go binary on demand.
⚠️ This talks to DeepSeek's private web endpoints using a browser-impersonating HTTP client. It is for educational/research use. Endpoints, headers, and the PoW scheme can change at any time and break this client.
Each chat request goes through the following flow:
- Create a chat session —
POST /api/v0/chat_session/createreturns a session id. - Request a PoW challenge —
POST /api/v0/chat/create_pow_challengereturns a challenge containing asalt,expire_at,challenge(target hash),difficulty,signature, andalgorithm. - Solve the PoW — find an integer
wsuch thatKeccak256(f"{salt}_{expire_at}_" + str(w))equals the target hash, searchingwin[0, difficulty]. This is done by the Go solver. - Submit the completion — the solution is base64-encoded into an
x-ds-pow-responseheader and sent withPOST /api/v0/chat/completion. - Stream the answer — the response is a Server-Sent Events (SSE) stream of incremental deltas, which the client reassembles into the final
contentandthinkingtext.
chat.py ──(JSON over stdin)──▶ Solver/solver.py ──(subprocess)──▶ Solver/solve.go (Keccak-256)
▲ │
└────────────────────── solution w ◀────────────────────────────────────┘
| File | Purpose |
|---|---|
chat.py |
The async DeepseekChat client: session creation, PoW orchestration, completion request, and SSE stream parsing. |
Solver/solver.py |
Python wrapper around the Go solver. Calls solve_pow(prefix, target, difficulty); auto-builds the Go binary on first use (or when the source changes). |
Solver/solve.go |
Standalone Keccak-256 proof-of-work solver. Reads a JSON request on stdin (or flags) and prints the solution as JSON. |
Solver/solver_bin |
The compiled Go binary (generated; rebuilt automatically when solve.go changes). |
- Python 3.10+ (the code uses
int | Nonestyle type hints) - Go installed and available on
PATH(the Python wrapper compilessolve.goautomatically on first run) - The
wreqlibrary — a browser-impersonating async HTTP client (used here withEmulation.Chrome147)
pip install wreq-
Open
chat.pyand replace the placeholder bearer token in theauthorizationheader:'authorization': 'Bearer TOKENHERE',
with a valid token from an authenticated
chat.deepseek.comsession (copy it from your browser's network requests). -
Run the client:
python chat.py
The
main()entry point sends a sample prompt and prints the result:ds = DeepseekChat() chat = await ds.chat_with_model("Write me a python script that prints hello world") print(chat)
chat_with_modelreturns a dict:{ "content": "...the model's answer...", "thinking": "...reasoning text, if thinking_enabled...", }
The completion payload in chat_with_model exposes a few toggles you can adjust:
thinking_enabled— request the model's reasoning trace (collected intothinking).search_enabled— enable web search (currentlyTrue).model_type,parent_message_id,action— left as defaults/None.
The Go solver is usable on its own, independent of the chat client:
from Solver.solver import solve_pow
res = solve_pow(prefix="salt_1700000000_", target="<64-hex-char-keccak256>", difficulty=144000)
print(res["ok"], res["w"], res["hash"], res["match"])Or invoke the binary directly with JSON on stdin:
echo '{"prefix":"salt_1700000000_","target":"<64 hex chars>","difficulty":144000}' | ./Solver/solver_binIt also accepts flags: -prefix, -target, -difficulty.
The response JSON contains: ok, w (the solution), message (prefix + w), hash, match, prefix, target, difficulty, and error (on failure).
- The solver is a linear brute force over
[0, difficulty]; it returnsok: falseif no solution is found in range. solver_binis rebuilt automatically wheneversolve.gois newer, so you generally never rungo buildyourself.- Several source comments and messages are in German.