Локальный OpenAI-compatible API proxy для DeepSeek Web Chat
License MIT Node.js 18 plus No npm dependencies OpenAI compatible
Быстрый старт • Возможности • Примеры • Модели • Endpoints • Open WebUI
FreeDeepseekAPI поднимает локальный API-сервер для DeepSeek Web Chat (chat.deepseek.com) и позволяет подключать DeepSeek Web к Open WebUI, LiteLLM, Hermes, Claude Code, OpenAI SDK-style клиентам и другим OpenAI-compatible инструментам.
Проект работает через ваш обычный залогиненный аккаунт DeepSeek в отдельном Chrome-профиле. Локальный сервер принимает API-запросы, а дальше сам ходит в DeepSeek Web через сохранённую browser-сессию.
⚠️ Это экспериментальный web-chat proxy. DeepSeek может менять внутренний Web API без предупреждения. Для production-кейсов надёжнее официальный платный API DeepSeek.
ForgetMeAI: https://t.me/forgetmeai
- Что это даёт
- Возможности
- Быстрый старт
- Windows запуск
- Linux / Chromium запуск
- VPS / headless запуск
- Diagnostics / doctor
- Session reuse и сброс чатов
- Multi-account pool
- Идеи для консольной авторизации
- Проверка работы
- Примеры запросов
- Модели
- Endpoints
- Open WebUI
- Обновить логин
- Статус проекта
- Использовать DeepSeek Web как локальный API endpoint.
- Подключать DeepSeek к Open WebUI и другим OpenAI-compatible клиентам.
- Получать обычные JSON-ответы или streaming SSE.
- Использовать reasoning-модели с отдельным
reasoning_content. - Работать с Anthropic Messages API shim для Claude Code / Anthropic SDK.
- Использовать OpenAI Responses API shim для новых OpenAI/Codex-style клиентов.
- Держать отдельные web-сессии для разных агентов/users.
- OpenAI-compatible API:
POST /v1/chat/completions - Anthropic-compatible shim:
POST /v1/messages - OpenAI Responses shim:
POST /v1/responses - Streaming: SSE chunks и обычные non-stream JSON-ответы
- Reasoning output: отдельный
reasoning_contentдля thinking-моделей - Tool calling: парсинг OpenAI tools, Anthropic tools и Responses function tools
- Model capabilities:
GET /v1/model-capabilitiesс alias → real web mode - Agent sessions: отдельная DeepSeek-сессия на
user/ agent id - Session recovery: авто-сброс устаревших chains/sessions
- Zero dependencies: Node.js 18+, без npm-зависимостей
git clone https://github.com/ForgetMeAI/FreeDeepseekAPI.git
cd FreeDeepseekAPI
npm run auth
npm startnpm run auth открывает меню авторизации:
- выберите пункт
1; - войдите в DeepSeek в отдельном Chrome-профиле;
- отправьте короткое сообщение вроде
ok; - вернитесь в терминал и нажмите Enter.
npm start показывает меню запуска:
1— авторизоваться / обновить DeepSeek login2— показать модели и статусы3— запустить proxy4— выйти
Для headless/CI-запуска без меню:
NON_INTERACTIVE=1 npm start
# или
SKIP_ACCOUNT_MENU=1 npm startПо умолчанию сервер слушает:
http://localhost:9655
git clone https://github.com/ForgetMeAI/FreeDeepseekAPI.git cd FreeDeepseekAPI npm run auth npm start
Если Chrome установлен нестандартно, явно укажите путь:
$env:CHROME_PATH="C:\Program Files\Google\Chrome\Application\chrome.exe" npm run auth
Если Chrome не найден, npm run auth теперь печатает готовые инструкции для Windows/macOS/Linux вместо загадочного stack trace.
git clone https://github.com/ForgetMeAI/FreeDeepseekAPI.git cd FreeDeepseekAPI CHROME_PATH=$(which chromium) npm run auth npm start
Если Chromium называется иначе:
CHROME_PATH=$(which chromium-browser) npm run auth # или CHROME_PATH=$(which google-chrome) npm run auth
Самый надёжный flow без Chrome на сервере:
- На домашнем ПК, где есть GUI/Chrome:
npm run auth
- Скопируйте
deepseek-auth.jsonна VPS:
scp deepseek-auth.json user@your-vps:/opt/FreeDeepseekAPI/deepseek-auth.json
- На VPS импортируйте/проверьте файл и выставьте безопасные права:
cd /opt/FreeDeepseekAPI
npm run auth:import -- --input ./deepseek-auth.json
npm run doctor -- --offline- Запускайте proxy без интерактивного меню:
NON_INTERACTIVE=1 npm start
Можно импортировать не только готовый deepseek-auth.json, но и browser cookie export:
DEEPSEEK_TOKEN="<token>" npm run auth:import -- --input ./cookies.jsonВажно:
deepseek-auth.json— это доступ к вашему DeepSeek Web login. Не коммитьте, не публикуйте, храните с правами0600.
npm run doctor
# без сетевых запросов к DeepSeek:
npm run doctor -- --offlinedoctor проверяет:
- найден ли
deepseek-auth.json/DEEPSEEK_AUTH_DIR; - валидный ли JSON;
- есть ли
token,cookie,wasmUrl; - безопасные ли права файла на macOS/Linux (
0600); - при обычном запуске — доступен ли DeepSeek PoW endpoint.
Если видите data.biz_data is null, fetch failed, 401/403/429 или Hermes/OpenCode не видит модели — первым делом запускайте npm run doctor.
FreeDeepseekAPI не создаёт новый DeepSeek чат на каждый HTTP-запрос без причины. Логика такая:
- один
x-agent-session,sessionилиuser→ одна DeepSeek chat session; - если session id уже есть — proxy переиспользует его и продолжает chain через
parent_message_id; - auto-reset происходит при TTL, ошибке DeepSeek session или слишком длинной цепочке сообщений;
- локальная history сохраняется коротким контекстом, чтобы новая DeepSeek session могла продолжить разговор.
Явно задать agent/session:
curl -X POST http://localhost:9655/v1/chat/completions \ -H "Content-Type: application/json" \ -H "x-agent-session: my-agent" \ -d '{"model":"deepseek-chat","messages":[{"role":"user","content":"Привет"}]}'
Посмотреть активные sessions:
curl http://localhost:9655/v1/sessions
Сбросить одну session:
curl -X POST "http://localhost:9655/reset-session?agent=my-agent"Сбросить все sessions:
curl -X POST "http://localhost:9655/reset-session?agent=all"Почему чаты всё равно появляются в DeepSeek Web: proxy работает через внутренний Web Chat API, а DeepSeek хранит реальные chat sessions у себя. Это нормально для web-proxy. Задача session reuse — не плодить новые чаты без необходимости и аккуратно сбрасываться только когда chain протух/сломался.
Можно подключить несколько auth-файлов. Правильная модель: sticky account per agent/session — proxy не переключает аккаунт внутри живой DeepSeek-сессии. Если аккаунт получил 401/403/429 и ушёл в cooldown, session безопасно сбрасывается и новый запрос может перейти на другой доступный аккаунт.
Вариант 1 — директория с auth-файлами:
mkdir -p accounts
cp deepseek-auth-main.json accounts/main.json
cp deepseek-auth-backup.json accounts/backup.json
chmod 600 accounts/*.json
DEEPSEEK_AUTH_DIR=./accounts NON_INTERACTIVE=1 npm startВариант 2 — список файлов:
DEEPSEEK_AUTH_PATH="./accounts/main.json,./accounts/backup.json" NON_INTERACTIVE=1 npm startКак работает pool:
- новый agent/session получает доступный аккаунт round-robin;
- выбранный аккаунт закрепляется за session (
sticky); - при
401,403,429аккаунт уходит в cooldown; - если sticky-аккаунт session ушёл в cooldown, старая DeepSeek-сессия сбрасывается, чтобы не долбить rate-limited/expired аккаунт;
- статус аккаунтов виден в
/healthбез путей к auth-файлам и без имён файлов; - auth-файлы должны храниться с правами
0600.
Настроить cooldown:
DEEPSEEK_ACCOUNT_COOLDOWN_MS=600000 npm start
Парольный flow из PR #3 можно делать, но безопаснее не хранить пароль и не делать это дефолтом. Нормальная реализация:
npm run auth:consoleспрашивает email/телефон и пароль через hidden prompt.- Пароль держится только в памяти процесса, не пишется в файлы/logs/history.
- Скрипт повторяет Web login flow через
fetch/CDP: получает captcha/verify challenge, отдаёт человеку ссылку/код, ждёт подтверждение. - После успешного login сохраняется только
deepseek-auth.jsonстандартного формата. - Если DeepSeek просит captcha/2FA — скрипт честно говорит "открой ссылку, пройди проверку, нажми Enter", а не пытается обходить защиту.
- Для VPS лучше режим
auth:console --no-save-password --output deepseek-auth.json.
Минимальный безопасный MVP: console auth только интерактивный, без env-пароля. Допустимый automation-вариант: DEEPSEEK_EMAIL=... npm run auth:console, но пароль всё равно вводится hidden prompt.
curl http://localhost:9655/ curl http://localhost:9655/v1/models curl http://localhost:9655/v1/model-capabilities
Если всё ок, /health вернёт статус сервера, список поддерживаемых aliases и config_ready: true.
curl -X POST http://localhost:9655/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "deepseek-chat", "messages": [{"role": "user", "content": "Привет! Ответь одной фразой."}], "stream": false }'
curl -X POST http://localhost:9655/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "deepseek-reasoner", "messages": [{"role": "user", "content": "Реши коротко: почему небо голубое?"}], "stream": false }'
Для reasoning-моделей API отдаёт цепочку размышления отдельно от финального ответа:
- non-stream:
choices[0].message.reasoning_content - stream:
choices[0].delta.reasoning_content - usage:
usage.completion_tokens_details.reasoning_tokens
reasoning_tokens — приблизительная оценка по извлечённому DeepSeek Web THINK-тексту, потому что web stream не отдаёт официальный token usage по reasoning отдельно.
curl -X POST http://localhost:9655/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "deepseek-chat-search", "messages": [{"role": "user", "content": "Найди свежий факт про DeepSeek и ответь кратко."}], "stream": false }'
curl -N -X POST http://localhost:9655/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "deepseek-chat", "messages": [{"role": "user", "content": "Напиши короткую шутку."}], "stream": true }'
curl -X POST http://localhost:9655/v1/messages \ -H "Content-Type: application/json" \ -d '{ "model": "deepseek-chat", "max_tokens": 512, "messages": [{"role": "user", "content": "Ответь ровно OK"}], "stream": false }'
Для Claude Code можно указывать backend напрямую:
export ANTHROPIC_BASE_URL="http://127.0.0.1:9655" export ANTHROPIC_AUTH_TOKEN="dummy-key" export CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1 claude --model deepseek-chat
curl -X POST http://localhost:9655/v1/responses \ -H "Content-Type: application/json" \ -d '{ "model": "deepseek-chat", "input": "Ответь ровно OK", "stream": false }'
FreeDeepseekAPI принимает:
- OpenAI
tools; - Anthropic
tools; - Responses API function tools.
Прокси просит DeepSeek вернуть строгий JSON tool call, но также умеет парсить fallback-форматы:
TOOL_CALL:- fenced JSON
<tool_call>...</tool_call>
GET /v1/models возвращает только aliases, которые сейчас проверены и работают через этот proxy.
| Alias | Web mode | Reasoning | Web search | Комментарий |
|---|---|---|---|---|
deepseek-chat |
Быстрый / default |
нет | нет | базовый chat |
deepseek-v3 |
Быстрый / default |
нет | нет | совместимый alias |
deepseek-default |
Быстрый / default |
нет | нет | совместимый alias |
deepseek-reasoner |
Быстрый / default |
да | нет | thinking_enabled=true |
deepseek-r1 |
Быстрый / default |
да | нет | R1-compatible alias |
deepseek-chat-search |
Быстрый / default |
нет | да | web search |
deepseek-default-search |
Быстрый / default |
нет | да | web search alias |
deepseek-reasoner-search |
Быстрый / default |
да | да | reasoning + search |
deepseek-r1-search |
Быстрый / default |
да | да | R1-compatible + search |
deepseek-expert |
Эксперт / expert |
нет | нет | Expert mode |
deepseek-v4-pro |
Эксперт / expert |
да | нет | Expert + reasoning |
Полный маппинг:
curl http://localhost:9655/v1/model-capabilities
По официальной странице DeepSeek V4 Preview deepseek-chat и deepseek-reasoner сейчас route'ятся в deepseek-v4-flash non-thinking/thinking. В самом chat.deepseek.com direct stream точное имя чекпойнта не отдаётся (model: ""), поэтому proxy фиксирует одновременно web-режим (default / Быстрый) и актуальную официальную маршрутизацию (DeepSeek-V4-Flash).
Текущий вывод DeepSeek Web remote config показывает такие web-режимы:
default/ UIБыстрый— работает; поддерживаетthinking_enabledиsearch_enabled.expert/ UIЭксперт— работает через актуальный web-контракт (x-client-version=2.0.0) и поддерживаетthinking_enabled. В/v1/modelsвыдаютсяdeepseek-expertбез reasoning иdeepseek-v4-proкак Expert + reasoning.vision/ UIРаспознавание— виден в remote config, но сейчас direct Web API возвращаетbackend_err_by_model(Vision is temporarily unavailable). Поэтомуdeepseek-visionскрыт из/v1/models.
Search для Expert по remote config недоступен, поэтому deepseek-expert-search остаётся unsupported.
| Method | Path | Назначение |
|---|---|---|
GET |
/ или /health |
статус proxy |
GET |
/v1/models |
список рабочих OpenAI-compatible aliases |
GET |
/v1/model-capabilities |
полный маппинг aliases, real model, capabilities |
POST |
/v1/chat/completions |
OpenAI-compatible Chat Completions |
POST |
/v1/messages |
Anthropic Messages API shim |
POST |
/v1/responses |
OpenAI Responses API shim |
GET |
/v1/sessions |
активные локальные agent sessions |
POST |
/reset-session?agent=<id> |
сбросить одну session |
POST |
/reset-session?agent=all |
сбросить все sessions |
Base URL для Open WebUI в Docker:
http://host.docker.internal:9655/v1
Для локального запуска без Docker:
http://localhost:9655/v1
API key можно указать любой: proxy сам ходит в DeepSeek Web через сохранённую browser-сессию.
npm run auth npm start
Если DeepSeek начал отвечать 401, 403 или просит новый PoW/session — повторите npm run auth и обновите сохранённую browser-сессию.
Локальные файлы авторизации не должны попадать в GitHub:
deepseek-auth.json.chrome-profile-deepseek/.env
Они уже добавлены в .gitignore.
Синтаксическая проверка проекта:
npm testLive smoke-тесты против запущенного локального proxy:
BASE_URL=http://127.0.0.1:9655 MODEL=deepseek-chat npm run test:live
FreeDeepseekAPI — экспериментальный web-chat proxy для локального использования и интеграций. Он зависит от текущего контракта DeepSeek Web Chat, поэтому при изменениях на стороне DeepSeek может потребоваться обновление auth/session logic или model mapping.
Если что-то перестало работать:
- обновите логин через
npm run auth; - проверьте
/v1/model-capabilities; - повторите запрос на свежей сессии;
- если проблема сохраняется — вероятно, DeepSeek изменил внутренний Web API.
ForgetMeAI · Telegram