DeepSeek: Cheap API, MIT Weights, and a Name Trap
DeepSeek ships language models in two shapes at once: as a paid API compatible with the OpenAI format, and as weights you can download from Hugging Face under the MIT license. The two paths carry different costs, different limits, and different legal consequences, so it pays to separate them from the start, before someone on the team says "but it is open source anyway".
What DeepSeek actually offers
The API documentation currently lists three model names. All three support a one million token context, a maximum output of 384 thousand tokens, and thinking mode enabled by default. The aliases are stable: deepseek-v4-flash points today at the DeepSeek-V4-Flash-0731 release and deepseek-v4-pro at DeepSeek-V4-Pro-0813, so your code needs no change when the vendor swaps versions. That is convenient, and it has a flip side: you cannot pin a specific release through the model name, and behaviour can shift with no change on your side.
| Model name | Release | Context | Maximum output | Concurrency limit |
|---|---|---|---|---|
deepseek-v4-flash | DeepSeek-V4-Flash-0731 | 1M tokens | 384K tokens | 2500 |
deepseek-v4-pro | DeepSeek-V4-Pro-0813 | 1M tokens | 384K tokens | 500 |
deepseek-v4-flash-vision-exp | DeepSeek-V4-Flash-Vision-Exp | 1M tokens | 384K tokens | 2500 |
The third model additionally accepts images and is marked experimental. It shipped on 21 August 2026, one day before this text was written, so treat it as a preview rather than a production foundation. Images are converted into tokens based on their dimensions and billed alongside text at the input rate.
The vendor exposes two base addresses: https://api.deepseek.com for the OpenAI format and https://api.deepseek.com/anthropic for the Anthropic format. Since 13 August 2026 the API also natively supports the Responses format. The concurrency limit is counted per account rather than per key, and it is the only hard limit described in the documentation: there is no separate requests per minute or tokens per minute cap. Exceeding concurrency returns HTTP 429. Raising the limit goes through a request form and, according to the documentation, carries no extra charge.
The user_id parameter is a separate matter. You pass it in extra_body with the OpenAI SDK or in metadata with the Anthropic SDK. It does three jobs at once: it isolates the context cache between your application's users, isolates scheduling, and separates content moderation. It must match [a-zA-Z0-9\-_]+ and stay under 512 characters. The documentation explicitly asks you to keep personal data out of it, which is easy to miss when you already have user identifiers at hand.
The name trap: the deepseek package is not DeepSeek
The most common starting mistake is typing pip install deepseek and assuming it is the official client. It is not. Version 1.0.0 of the deepseek package on PyPI is published by Deskpai.com, the contact address is dev@deskpai.com, and the project page points at github.com/deskpai/deepseek. The latest release dates to 3 January 2025. This is a third-party wrapper, not a DeepSeek product.
Checking the license across three sources gives three different answers, and that is the heart of the problem with this package. The PyPI metadata declares Apache-2.0. The published wheel weighs 4542 bytes and holds exactly seven files: deepseek/__init__.py, deepseek/api.py, deepseek/const.py and four files in the dist-info directory, none of which carries any license text. The GitHub repository has no LICENSE file at its root, while README.md shows a "DOSL-1.0" badge and points to a license living in an entirely different repository from the same publisher. Three sources, three states: an Apache 2.0 declaration, no text at all in the package, and a custom license mentioned in the description.
The code inside has aged too. The const.py file hardcodes three addresses: https://api.deepseek.com/chat/completions, https://api.deepseek.com/beta/completions and https://api.deepseek.com/user/balance. The chat_completion method defaults to the model deepseek-chat, which the current documentation no longer lists, and sends a fixed payload with max_tokens set to 2048, temperature set to 1 and tool_choice set to none. The package predates thinking mode and the reasoning_effort parameter, so it knows neither. Its only dependency is requests.
On the npm side the picture is similar, only thinner. The deepseek package there sits at version 0.0.2 from 22 January 2025, the description reads "Coming soon...", the package contains three files totalling 311 bytes unpacked, and the manifest has no license field at all. It is a claimed name, not a library.
DeepSeek publishes no SDK of its own and does not pretend otherwise. The getting started documentation says plainly that the API is compatible with the OpenAI and Anthropic formats and that changing the configuration of an existing SDK is enough. Every example in the documentation uses the openai and anthropic libraries. That is the path shown below.
How the vendor recommends you connect
The Python version is an ordinary OpenAI client with a swapped base_url. The openai library sits at version 3.3.1 on PyPI at the time of writing, under Apache 2.0.
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ.get("DEEPSEEK_API_KEY"),
base_url="https://api.deepseek.com",
)
response = client.chat.completions.create(
model="deepseek-v4-pro",
messages=[
{"role": "system", "content": "You are a helpful assistant"},
{"role": "user", "content": "Hello"},
],
stream=False,
reasoning_effort="high",
extra_body={"thinking": {"type": "enabled"}, "user_id": "tenant-42"},
)
print(response.choices[0].message.reasoning_content)
print(response.choices[0].message.content)In Node it is the same thing through baseURL. The openai package on npm is currently at version 7.5.0, also under Apache 2.0.
import OpenAI from "openai";
const openai = new OpenAI({
baseURL: "https://api.deepseek.com",
apiKey: process.env.DEEPSEEK_API_KEY,
});
const completion = await openai.chat.completions.create({
messages: [{ role: "system", content: "You are a helpful assistant." }],
model: "deepseek-v4-pro",
thinking: { type: "enabled" },
reasoning_effort: "high",
stream: false,
});
console.log(completion.choices[0].message.content);If you prefer the Anthropic format, the base address is https://api.deepseek.com/anthropic, thinking mode is driven by the reasoning.effort field, and the client identifier goes into metadata.user_id. The choice of format depends on what your code already speaks. If you build on the SDK from OpenAI, stay with the OpenAI format. If your code already speaks the Claude format, use the second address and leave your client layer alone.
Thinking mode and the parameters that stop working
Thinking mode is on by default and the default effort level is high. Control has two layers: the thinking switch and the reasoning_effort level. The mapping declared by the documentation is identical for both text models and it is not linear.
Requested reasoning_effort | Actual model effort |
|---|---|
low | low |
medium | high |
high | high |
xhigh | high |
max | max |
One consequence of that table can surprise you while tuning cost: medium and xhigh are not separate levels, they are aliases of high. There are three real steps.
The second set of surprises concerns parameters that simply do nothing in thinking mode. The documentation lists temperature, top_p, presence_penalty and frequency_penalty. Setting them raises no error, because the API stays compatible with existing software, but has no effect either. If you keep a layer that tunes temperature by task type, that tuning is dead in thinking mode.
The third point is harder and easy to forget while building an agent. Reasoning text comes back in the reasoning_content field, next to content. When a request carries no tools parameter, earlier reasoning_content can be dropped while concatenating context, because the API ignores it anyway. When the request does carry tools, reasoning_content must be sent back to the API on every following user turn, even on turns with no tool call. Omitting it ends with a 400 response. That is a real difference from most OpenAI-compatible implementations, so a homegrown conversation history layer needs a fix.
Pricing, the context cache, and peak hours
The new price list took effect at 16:00 UTC on 16 August 2026 and introduces a split between peak and off-peak hours. Rates below are per million tokens, in dollars.
| Line item | flash off-peak | flash peak | pro off-peak | pro peak |
|---|---|---|---|---|
| Input, cache hit | 0.007 | 0.014 | 0.022 | 0.044 |
| Input, cache miss | 0.22 | 0.44 | 0.66 | 1.32 |
| Output | 0.66 | 1.32 | 1.98 | 3.96 |
Peak hours run 01:00 to 04:00 and 06:00 to 10:00 UTC. That adds up to seven peak hours a day and seventeen off-peak hours, so the lower rate is effectively the default price rather than a promotion. For batch jobs run from Europe it means an evening queue lands in the cheap window with no scheduling tricks at all.
The arithmetic of that table fails to come out round in two places. First, the pro model costs exactly three times the flash price on the cache miss line and on the output line, but on the cache hit line it is 0.022 instead of 0.021, slightly more than triple. Second, the miss to hit ratio differs between models: for pro it is exactly 30 to 1, for flash roughly 31.4 to 1. If you build a cost calculator, do not assume a single multiplier for both models.
The context cache is on by default for everyone and needs no code changes, but the hit rules are stricter than plain prefix matching. Each request creates cache units at the end of the user input and at the end of the model output. A later request hits the cache only when it matches such a unit in full. When two requests share a beginning but differ at the end, neither hits the cache, though the system detects the common prefix and stores it as a separate unit that only a third request can use. For long inputs and outputs, units are also carved out at fixed token intervals. You check the state in the response, in the prompt_cache_hit_tokens and prompt_cache_miss_tokens fields under usage.
usage = response.usage
hit = usage.prompt_cache_hit_tokens
miss = usage.prompt_cache_miss_tokens
# flash off-peak rates, USD per million tokens
cost_input = hit / 1_000_000 * 0.007 + miss / 1_000_000 * 0.22
cost_output = usage.completion_tokens / 1_000_000 * 0.66
print(round(cost_input + cost_output, 6))The documentation states that the cache works on a best-effort basis with no guarantee of a full hit rate, that building an entry takes seconds, and that an unused entry usually disappears within a few hours to a few days. Planning a budget purely on the hit rate is therefore risky.
Hugging Face weights versus the vendor API
Open weights and the API are two different products with different licenses. The deepseek-ai organisation on Hugging Face publishes weights you can download and run yourself. The DeepSeek-V4-Pro-0813 model card states plainly that the repository and the model weights are covered by the MIT license, and the same tag appears on DeepSeek-V4-Flash-0731, DeepSeek-V3.2-Exp, DeepSeek-V3.1 and DeepSeek-R1.
It was not always so, which is why the license has to be checked per model. The original DeepSeek-V3 repository from December 2024 carries two separate files: LICENSE-CODE with MIT text and LICENSE-MODEL with a document titled "DEEPSEEK LICENSE AGREEMENT Version 1.0" dated 23 October 2023. That second license contains use-based restrictions and requires derivative releases to carry the same restrictions forward. Only from DeepSeek-V3-0324 onward do the repositories ship a single LICENSE file with MIT text. If someone on the team inherited an older checkpoint, its license is not the one that governs the new releases.
The scale of those weights is often underestimated. The tensor index reported by Hugging Face gives roughly 1.65 trillion parameters for DeepSeek-V4-Pro-0813 and roughly 304 billion for DeepSeek-V4-Flash-0731. The Pro configuration lists 61 layers, 384 routed experts plus one shared expert, six experts per token, and fp8 quantisation in the e4m3 format. At roughly one byte per parameter, the Pro weight files land in the order of 1.6 terabytes and Flash in the order of 300 gigabytes. The model card gives a sample serving command for a single node with four GB300 cards.
vllm serve deepseek-ai/DeepSeek-V4-Pro-0813 \
--trust-remote-code --kv-cache-dtype fp8 --block-size 256 \
--data-parallel-size 4 --enable-expert-parallel \
--moe-backend deep_gemm_mega_moe \
--attention-config '{"use_fp4_indexer_cache": true}' \
--speculative-config '{"method":"dspark","num_speculative_tokens":7,"draft_sample_method":"greedy"}'This is data centre hardware, not a laptop. Sensible local paths run through vLLM or SGLang on rented cards, not through Ollama, which suits smaller models and distillations. One more detail breaks many off-the-shelf integrations: the DeepSeek-V4-Pro-0813 release contains no Jinja chat template. Instead the repository ships an encoding directory with the encode_messages and parse_message_from_completion_text functions, which you have to call yourself to build the prompt and parse the reply.
| Criterion | DeepSeek API | Hugging Face weights |
|---|---|---|
| License | platform terms, no open source license | MIT for releases from V3-0324 onward |
| Entry cost | topping up a balance | GPU cards or rental |
| Processing location | vendor servers | your infrastructure |
| Version pinning | alias points at the current release | a specific repository commit |
| Context cache | built in, billed separately | you configure it yourself |
Data, compliance, and the risk of a vendor outside the Union
The privacy policy is issued by Hangzhou DeepSeek Artificial Intelligence Co., Ltd. with a registered address in China, and the data contact address is privacy@deepseek.com. The document states plainly that personal data may be stored on a server located outside the country where the user lives. The retention period is described deliberately broadly: data is kept for as long as the account exists, plus wherever contractual and legal obligations or a legitimate business interest require it, including improving and developing the services. In other words, no hard deletion deadline is given for request content.
For a team inside the European Union this translates into concrete tasks rather than vague worry. A transfer to a third country needs a legal basis and an impact assessment. In the platform documentation I found no offer of processing inside an EU region and no ready template for a data processing agreement, so check that directly with the vendor before letting personal data reach this API. If the answer does not arrive in writing, that is an answer in itself.
The developer platform terms do carry one clause more favourable than several competitors offer. The section on inputs and outputs says you keep rights to your inputs, DeepSeek assigns the rights in outputs to you, and outputs may be used broadly, including for training other models, for example through distillation. Anyone building a smaller in-house model on synthetic data should read that section in full, because it explicitly permits a scenario forbidden by more than one competing set of terms.
Operational risk is the third dimension. There have been periods when the vendor limited registration of new accounts under load. The technical documentation does not record such events, so I will give no dates, though the mechanism is worth planning for: create the account and the key earlier than you need them, and keep a fallback path ready. The practical answer is a routing layer such as LiteLLM or OpenRouter, which lets you move traffic to another vendor without touching application code.
Looking at the OpenRouter catalogue turns up two numbers that do not match the vendor's own material. The deepseek/deepseek-v4-pro-0813 entry is priced at 1.188 dollars per million input tokens and 3.564 per million output tokens, exactly ninety percent of DeepSeek's peak rate. The deepseek/deepseek-v4-flash-0731 entry declares a context length of 1,310,720 tokens, while the config.json of the same model reports max_position_embeddings of 1,048,576. Aggregator catalogues also describe third-party host offerings, so differences are explainable, but do not copy them into your own documentation without checking the source.
The second Chinese vendor worth comparing is Qwen from Alibaba, which offers a wider range of model sizes plus separate variants for coding and for multimodal work. The difference that matters most legally lies in the weight licences: DeepSeek released the V4 family uniformly under MIT, whereas at Qwen the licence is a per-model field and can differ between neighbouring variants of the same series. The largest model in the family carries its own licence with revenue thresholds, and one of the coding models sits on a licence permitting non-commercial use only, so checking a single licence file before downloading weights is not caution here but necessity.
Common mistakes
Installing the deepseek package instead of openai is mistake number one, and its effect is not obvious right away, because the package does work. It sends a valid request to a valid address, only with a default model the current documentation no longer lists and with no support for thinking mode.
The second mistake is treating the MIT license of the weights as the license of the API. The weights may be downloaded, modified, and deployed commercially. Access to api.deepseek.com is governed by the agreement with the vendor, and nothing about that agreement follows from MIT.
The third mistake is dropping reasoning_content while assembling history in a tool-using agent. The code works fine on the first turn and falls over with a 400 on the second, once tools appears, which sends people hunting for a bug in the wrong place for hours.
The fourth mistake is tuning temperature in thinking mode. No error, no effect, and a false sense of control. If you need to steer randomness, turn thinking off explicitly with {"thinking": {"type": "disabled"}}.
The fifth mistake concerns budget. A cost forecast computed at the cache hit rate can be off by an order of magnitude, because the cache is best effort and entries expire. Compute the upper bound at the miss rate and at the peak rate, and treat any saving as a bonus.
The sixth mistake is writing an end user identifier into user_id as an email address or a document number. The documentation asks for no personal data in that field, and the [a-zA-Z0-9\-_]+ pattern would reject most addresses anyway. Use an irreversible hash.
FAQ
Does the package from pip install deepseek come from DeepSeek?
No. Version 1.0.0 on PyPI comes from Deskpai.com and the repository is github.com/deskpai/deepseek. The latest release is dated 3 January 2025, the wheel weighs 4542 bytes, carries no license file, and knows nothing about thinking mode. The vendor recommends the openai or anthropic library with a swapped base address.
Can I run DeepSeek-V4 on my own hardware?
Yes, the weights are on Hugging Face under MIT, but the scale is serious: roughly 1.65 trillion parameters for the Pro version and roughly 304 billion for Flash. The example on the model card assumes a node with four GB300 cards. For experiments on a single card, distillations and smaller models fit far better.
How does DeepSeek bill the context cache?
Through separate rates for input tokens that hit the cache and those that missed. A hit costs 0.007 dollars per million for flash off-peak and 0.022 for pro. The response returns prompt_cache_hit_tokens and prompt_cache_miss_tokens, so the real hit rate can be measured instead of assumed.
Is DeepSeek suitable for personal data from the European Union?
Not without further arrangements. The operator is a company based in China, the privacy policy allows storage outside the user's country, and no deletion deadline is given for request content. The platform documentation offers no EU region processing. For personal data, consider self-hosting the weights or a vendor inside the Union.
How much work is switching existing code to DeepSeek?
With the OpenAI format it is usually two lines: base_url and the model name. The real work starts afterwards, around handling reasoning_content in tool-using agents, around sampling parameters that do nothing in thinking mode, and around regression tests, because the model alias points at the current release.
Sources: pricing and model list in the API documentation, the DeepSeek-V4-Pro-0813 model card, the deepseek package entry on PyPI.