DEV Community

Fundiman
Fundiman

Posted on

dsk++ — I rewrote a forgotten DeepSeek library to be fully async (and added a bunch of stuff)

A while back, xtekky wrote a small library called deepseek4free for interacting with DeepSeek's chat infrastructure. It worked, but it was synchronous — meaning it blocked the event loop on every API call, making it painful to use in any async Python project.

I needed it for a Discord bot I was building, and the blocking behavior was causing real problems. So I rewrote it.

The result is dskpp (dsk++) — a drop-in async replacement that adds a few things the original never had.


What's new in dsk++

  • Fully async — built on curl_cffi async sessions, async for streaming, asyncio.to_thread() for WASM PoW
  • Concurrent file uploadsasyncio.gather() uploads multiple files simultaneously
  • Session deletionawait api.delete_chat_session(session_id)
  • Conversation historyawait api.get_history(session_id)
  • Proper error hierarchyAuthenticationError, RateLimitError, NetworkError, CloudflareError, UploadFilesUnavailable, APIError
  • Automatic Cloudflare detection and cookie refresh
  • Docker support via DOCKERMODE=true

The architecture

The library has three layers:

API layer (api.py) handles session management, streaming SSE parsing, file uploads, and automatic retry on Cloudflare blocks.

Bypass layer (server.py) is a FastAPI + Chromium automation server that solves Cloudflare challenges and extracts cookies.

PoW layer (pow.py) runs the WASM-based proof-of-work solver via asyncio.to_thread() so it doesn't block your event loop during CPU-bound hashing.


Quick example

import asyncio
from dskpp.api import DeepSeekAPI

async def main():
    api = DeepSeekAPI("your_token_here")

    session = await api.create_chat_session()

    # Upload files concurrently
    file_ids = await api.upload_files(["report.pdf", "data.xlsx"])

    # Stream response
    async for chunk in api.chat_completion(
        session,
        "Summarize these files",
        ref_file_ids=file_ids,
        search_enabled=False
    ):
        print(chunk.get("content", ""), end="")

    await api.delete_chat_session(session)
    await api.close()

asyncio.run(main())
Enter fullscreen mode Exit fullscreen mode

Before using the API, you need to generate cookies once:

python run_and_get_cookies.py
Enter fullscreen mode Exit fullscreen mode

This launches Chromium, solves the Cloudflare challenge, and stores cookies locally. After that, the client handles refresh automatically.


Getting your token

Log into chat.deepseek.com, open DevTools, go to Application → Local Storage → chat.deepseek.com → USER_TOKEN.


A word of caution

This is built on reverse-engineered infrastructure. DeepSeek can change their API at any time and break things. It may also violate their ToS — use at your own risk and don't do anything that would get your account banned.


Why bother?

The original library was solid but unmaintained and sync-only. For anyone building bots, automation tools, or anything async in Python, a blocking DeepSeek client is a dead end. This fixes that. Also not everyone can afford the DeepSeek API, so this helps people automate the web interface endpoints for chat.

Credit to xtekky and Doremii109 whose work this builds on.


GitHub → Fundiman/dskpp

Stars appreciated 🥺

Top comments (0)