DeepSeek-V4.1-Flash Vision API: How to Send Images to DeepSeek's Native Multimodal Model

Send images to DeepSeek-V4.1-Flash via the deepseek-flash id: base64, URL, and file ID formats, the detail field, image pricing, and an Apidog test loop.

Ashley Innocent

Ashley Innocent

10 September 2026

DeepSeek-V4.1-Flash Vision API: How to Send Images to DeepSeek's Native Multimodal Model

Apidog for Enterprise

On-Premises Deploy

SSO & RBAC

SOC 2 Compliant

Explore Apidog Enterprise

DeepSeek’s vision support stopped being a side project on September 10, 2026. With the GA release of DeepSeek-V4.1-Flash, image input lives in the main model behind one id, deepseek-flash. There is no separate vision build and no “Exp” suffix. The release note retires both deepseek-v4-flash and deepseek-v4-flash-vision-exp; requests to either name now land on V4.1-Flash.

That matters if you built on the experimental endpoint three weeks ago. The request format you wrote against V4-Flash-Vision-Exp still works, but the model reading your images is new: 763B parameters, with a vision encoder trained from scratch alongside the text backbone. This guide covers what “native multimodal” means in practice, the three ways to deliver an image, the detail parameter, what images cost, and how to build a repeatable vision test in Apidog that proves the old name and the new one behave the same way.

TL;DR

What “native multimodal” means here

Vision-Exp attached an image encoder to a finished text model. V4.1-Flash does it the other way around. According to the model card, images were part of the 45T-token pre-training corpus from the start, and the encoder is a new DeepSeek-ViT trained from scratch instead of borrowed from an existing vision model. The backbone is a 552B-parameter mixture of experts; with the encoder attached the total reaches 763B. Only 8B parameters are active during prefill and 16B during decode, which is how a model this large still runs at Flash speed and Flash prices. V4-Flash, the text-only model in the V4-Flash API guide, was the base that Vision-Exp extended.

DeepSeek reports these four vision scores in the model card. They’re the vendor’s own measurements, so treat them as claims until you’ve pushed your own documents through the API.

Benchmark What it measures V4.1-Flash
MMMU-Pro College-level questions that need both the image and the text to answer 56.5
CVBench Counting, depth ordering, and spatial relations in natural photos 77.9
DocVQA Question answering over scanned documents and forms 95.6
RefCOCO Locating the object a phrase refers to inside an image 86.0

For API users, DocVQA and RefCOCO are the rows to watch. Document QA is the score behind invoice and form extraction. RefCOCO is grounding: given “the Submit button below the email field”, can the model find it? That skill turns screenshots into agent actions. The architecture overview covers the text side and the tech report in more depth.

The request format: three ways to deliver an image

Nothing about the wire format changed. Call the Chat Completions endpoint at https://api.deepseek.com with the OpenAI SDK, put text and image parts in the same content array, and set the model to deepseek-flash. Here’s a full call that turns an invoice into JSON:

import base64, json
from openai import OpenAI

client = OpenAI(api_key="YOUR_DEEPSEEK_KEY", base_url="https://api.deepseek.com")

with open("invoice-2026-0912.png", "rb") as f:
    image_b64 = base64.b64encode(f.read()).decode()

schema_hint = (
    "Return only JSON with keys: invoice_number (string), issue_date (YYYY-MM-DD), "
    "vendor (string), currency (string), line_items (array of {description, quantity, "
    "unit_price, amount}), subtotal, tax, total (numbers)."
)

response = client.chat.completions.create(
    model="deepseek-flash",
    messages=[{
        "role": "user",
        "content": [
            {"type": "text", "text": schema_hint},
            {
                "type": "image_url",
                "image_url": {
                    "url": f"data:image/png;base64,{image_b64}",
                    "detail": "high",
                },
            },
        ],
    }],
    temperature=1.0,
    max_tokens=2048,
)

invoice = json.loads(response.choices[0].message.content)
print(invoice["invoice_number"], invoice["total"])
print(response.usage.prompt_tokens, "prompt tokens")

That’s option one, base64 inline: self-contained, capped at 32 MiB per image, and right for one-off calls or files that never leave your network.

Option two is an external URL. If the image already has a public link on a CDN or in object storage, skip the encoding and pass the link (up to 8,192 characters). This curl request reads a hosted pricing chart:

curl https://api.deepseek.com/chat/completions \
  -H "Authorization: Bearer $DEEPSEEK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek-flash",
    "messages": [{
      "role": "user",
      "content": [
        {"type": "text", "text": "List every plan name and its monthly price from this chart as a JSON array."},
        {"type": "image_url", "image_url": {"url": "https://assets.example-saas.com/pricing/plans-q3.png", "detail": "auto"}}
      ]
    }]
  }'

Option three is a file ID. Upload the image once through DeepSeek’s Files API, then reference it with a file part instead of re-sending the bytes:

{"type": "file", "file": {"file_id": "file-api-xxxxxxxxxxxxxxxx"}}

Pick file IDs whenever the same image appears in more than one request, such as a reference screenshot every test in a suite compares against. The full parameter walkthrough is in the V4.1-Flash API guide.

The detail parameter and request limits

detail is optional and lives inside the image_url object. The three values carried over from Vision-Exp:

The ceilings you’ll meet first:

Constraint Value
Inline base64 image up to 32 MiB
External URL length up to 8,192 characters
File ID reference supported through the Files API
Context window 1M tokens
Max output 384K tokens
detail values low, high/original, auto

The Vision-Exp guide listed further ceilings on image count, body size, and pixel dimensions. Those were published for the experimental model; check the API changelog before you depend on them for V4.1-Flash. One rule hasn’t changed: images belong in user messages. Put one in a system or assistant message and you get a 400.

What images cost on deepseek-flash

There’s no separate vision price. Images bill as input tokens at the Flash rate from the pricing page, effective September 10, 2026 at 04:00 UTC:

deepseek-flash, per 1M tokens Off-peak Peak
Input, cache hit $0.003 $0.006
Input, cache miss $0.15 $0.30
Output $0.60 $1.20

Peak hours are Monday to Friday, 01:00 to 04:00 and 06:00 to 10:00 UTC; off-peak is half price. On Vision-Exp, each image was billed at no more than 384 input tokens. Whether that cap carries over unchanged to V4.1-Flash is [VERIFY] against the docs. Every response’s usage.prompt_tokens reports the real count, which is why the Python example prints it.

If the 384-token cap holds, one image costs about $0.000115 at peak cache-miss rates and half that off-peak, so a thousand invoices come to roughly $0.12 of image input. Output dominates any real pipeline: 400 tokens of JSON per invoice costs about four times more than the image itself at peak. The lever is a tight response schema, not image downscaling. The peak, off-peak, and cache-hit math is worked through in DeepSeek-V4.1-Flash pricing explained; the short version is that cache-miss input is 32% cheaper than Vision-Exp charged in August.

Three use cases worth a pilot

Document extraction. Invoices, receipts, delivery notes, insurance forms. Prompt for a fixed JSON schema, send at detail: "high", and check that line items sum to the subtotal before you trust a record.

UI screenshots to test assertions. Capture a page after a deploy, ask whether the expected elements are present and where, and turn the answer into a pass/fail. RefCOCO is the relevant benchmark: the job is finding named elements.

Chart reading. Pull series names, axis labels, and plotted values out of a chart image into a table. Overlapping lines or unlabeled axes call for a human spot check.

Testing the vision endpoint in Apidog

Vision requests are painful to iterate on by hand: a base64 blob makes the JSON body unreadable, and comparing detail settings means juggling near-identical payloads. Here’s a loop that stays readable and reruns in one click.

  1. Set up an environment. Create variables for base_url, api_key, model (deepseek-flash), and detail (high). Switching the detail level later is a dropdown change, not a payload edit.
  2. Encode the image in a pre-request script. Instead of pasting base64 into the body, let a pre-request script encode the sample file and write the result to an image_b64 variable. The visible body stays a few lines long, and swapping the test image means changing one path.
  3. Save the request body with variables. Use "model": "{{model}}", "detail": "{{detail}}", and "url": "data:image/png;base64,{{image_b64}}". Save it as a test case so it’s reusable.
  4. Assert on the JSON shape. Assert that the response parses as JSON, invoice_number is a non-empty string, line_items is a non-empty array, total is a number, and usage.prompt_tokens sits below a threshold you choose. That turns “looks fine” into a pass/fail.
  5. Confirm the legacy name routes to the same model. Duplicate the saved request, set model to deepseek-v4-flash-vision-exp, and run both in one test scenario against the same image. Compare the extracted fields and the usage.prompt_tokens count. Matching results confirm what the release note states: both names hit V4.1-Flash, so you can rename in your config with confidence.
  6. Run it in CI. Run the scenario with apidog-cli on every prompt change, so a schema regression surfaces before production.

Download Apidog and the rig takes about fifteen minutes to build. Apidog tests the API layer, not the model host, so the same scenario works against any OpenAI-compatible endpoint you route through later.

Where this leaves you

The experimental endpoint proved the request format and the price point. V4.1-Flash keeps both and swaps in a model that saw images from its first training token. Point your client at deepseek-flash, keep detail in a variable, assert on the JSON you get back, and run the legacy name through the same Apidog scenario once to confirm the rerouting. After that, the only question left is accuracy on your own documents, and you now have a test that answers it.

Explore more

How to Use DeepSeek-V4.1-Flash for Free: Every Option in 2026

How to Use DeepSeek-V4.1-Flash for Free: Every Option in 2026

Every honest way to use DeepSeek-V4.1-Flash for free in 2026: chat app, MIT weights, router free tiers, and the $1.35/month official API math.

10 September 2026

How to Run DeepSeek-V4.1-Flash Locally ?

How to Run DeepSeek-V4.1-Flash Locally ?

Can you run DeepSeek-V4.1-Flash locally? The memory math for 552B MIT weights, the 890-byte FP4 KV cache, realistic hardware tiers, and setup commands.

10 September 2026

How to Use the DeepSeek-V4.1-Flash API?

How to Use the DeepSeek-V4.1-Flash API?

Call the DeepSeek-V4.1-Flash API: model id deepseek-flash, base URLs, first call in curl/Python/Node, reasoning effort, image input, streaming, pricing.

10 September 2026

Practice API Design-first in Apidog

Discover an easier way to build and use APIs

DeepSeek-V4.1-Flash Vision API: How to Send Images to DeepSeek's Native Multimodal Model