api development

How to Send Images to DeepSeek Vision-Exp API

How to Send Images to DeepSeek Vision-Exp API

The moment screenshots stop being “just pixels”

There’s a specific kind of frustration that hits when you’re staring at a screenshot on your screen and thinking, “I wish a model could read this the way a human would.” You can’t copy the text cleanly. The UI is too cramped. The chart labels are tiny. So you start looking for “vision” support and hit a wall: most APIs either want special SDKs, or they want you to upload files in some custom format.

DeepSeek’s deepseek-v4-flash-vision-exp model changes that: it accepts images alongside text in an OpenAI-compatible Chat Completions style request. That means you can keep the same overall mental model—messages with roles—while adding image blocks inside content.

Supported formats are JPEG, PNG, GIF, and WebP. One detail that matters in practice: the service detects the image format from the actual file contents, not from the filename or the MIME type you claim. That protects you from “looks like JPG” mistakes that happen during uploads.


The request shape: content becomes a list of blocks

If you’ve used the Chat Completions API before, you’ve likely passed content as a plain string. With deepseek-v4-flash-vision-exp, content becomes an array of blocks—each block can be text or an image.

Here’s the mental model:

  • role: who is sending the message (for example, user).
  • content (array): one or more blocks.
  • type: "text": a normal text chunk.
  • type: "image_url": an image reference the model should fetch and analyze.

Why does this block format matter? Because it lets you interleave instructions and images in a single message, which is great for tasks like “read this chart and summarize the takeaway.”


Three ways to send an image

DeepSeek supports three image input methods, all inside that same OpenAI-style chat structure. The best choice depends on where your image lives (local file vs. remote URL) and how often you plan to reuse it.

1) Inline Base64 (data URL): best for quick local experiments

Inline Base64 means you:

  1. Read the image bytes from disk.
  2. Convert them to Base64 (a text encoding of binary data).
  3. Embed the result into a data: URL that the API can decode.

In code, this looks like:

import base64
from openai import OpenAI

client = OpenAI(api_key="<DeepSeek API Key>", base_url="https://api.deepseek.com")

with open("image.jpg", "rb") as f:
 b64 = base64.b64encode(f.read()).decode("utf-8")

response = client.chat.completions.create(
 model="deepseek-v4-flash-vision-exp",
 messages=[{
 "role": "user",
 "content": [
 {"type": "text", "text": "What is in this image?"},
 {
 "type": "image_url",
 "image_url": {"url": f"data:image/jpeg;base64,{b64}"},
 },
 ],
 }],
)

print(response.choices[0].message.content)

Tradeoff: inline images count against the 48 MiB request body limit, because the Base64 text is part of the request.

2) External URL: best when your image already lives online

If your image is publicly reachable over http(s), you can pass a normal URL.

There are a few practical constraints to keep in mind:

  • The URL length limit is 8192 characters.
  • The image file can be up to 32 MiB.
  • The download must complete within 60 seconds.

Example:

response = client.chat.completions.create(
 model="deepseek-v4-flash-vision-exp",
 messages=[{
 "role": "user",
 "content": [
 {"type": "text", "text": "Describe this image."},
 {"type": "image_url", "image_url": {"url": "https://example.com/image.jpg"}},
 ],
 }],
)

print(response.choices[0].message.content)

3) Files API file_id: best for reuse and bigger images

When the same image shows up repeatedly—or when images get large—the Files API approach is the cleanest.

Workflow:

  1. Upload the image once with the Files API.
  2. Get back a file_id (it looks like file-api-...).
  3. Reference that file_id in future vision requests.

In the chat message, you use a file content block instead of image_url:

{
 "role": "user",
 "content": [
 {"type": "text", "text": "What is in this image?"},
 {"type": "file", "file_id": "file-api-xxxxxxxxxxxxxxxx"}
 ]
}

This is also how you avoid the inline Base64 size pain. Inline images and external URLs have stricter caps; file_id images are allowed to be larger.


Control processing speed/quality with detail

Vision doesn’t always need to preserve every pixel. DeepSeek lets you tune how the image is processed using detail.

For image_url inputs:

  • detail: "low": downscales to 512×512 before inference (faster/cheaper when fine detail isn’t required).
  • detail: "high" or "original": keeps the original image (equivalent here).
  • detail: "auto": currently behaves like "original".

Example:

{
 "type": "image_url",
 "image_url": {
 "url": "https://example.com/image.jpg",
 "detail": "low"
 }
}

Question worth asking when you wire this up: Do we really need OCR-level precision, or would a rough description be enough to drive the next step? Using low for the “rough step” can keep costs and latency under control.


Token usage: images aren’t free text-sized chunks

This part is genuinely tricky until you see how it behaves. Images get turned into vision tokens, and those tokens are billed together with text tokens.

DeepSeek automatically resizes images before inference:

  • Very small images (below roughly 384×384 total pixels) get scaled up while preserving aspect ratio.
  • Larger images get scaled down while preserving aspect ratio.

The key outcome: after resizing, the total pixel count is designed to be roughly equivalent to an 800×800 image. That means huge images don’t explode your token cost the way you might fear.

Even better (or more surprising): there’s an upper bound of 384 tokens per image. So a very large image and a moderately large one can consume the same number of image tokens after resizing.

Also, for multiple images, each image is counted independently under the same rule.

If you want a way to think about token cost more generally, DeepSeek describes tokens as the billing unit used by models, and their docs note the practical conversion from text to tokens depends on the tokenizer—not a fixed character count. (api-docs.deepseek.com)


Limits you’ll want to know before you hit them

Here are the big caps (the ones that tend to cause errors in real systems):

  • Supported formats: JPEG, PNG, GIF, WebP
  • External URL length: 8192 characters
  • Request body size (inline content counts here): 48 MiB
  • Max single image size (Base64 / external URL): 32 MiB
  • Max single image size (Files API file_id): 64 MiB
  • Max images per request: 600
  • Max total image size per request:
  • 64 MiB without file_id images
  • up to 200 MiB including file_id images
  • Max image dimension: 8192 px per side
  • drops to 4096 px per side when the request contains 15+ images

This set of rules pushes a clear engineering approach:

  • Prototype with Base64 until you understand your prompts and expected outputs.
  • Move to URLs when images already exist publicly.
  • Move to Files API when you hit size/reuse limits or when your app repeatedly analyzes the same assets.

Putting it all together: a practical screenshot workflow

Imagine an internal workflow where people send UI screenshots: you want to describe what changed, pull out key numeric labels from a chart, and convert the result into a structured summary.

A robust pattern looks like this:

  1. Start with an inline Base64 image while you’re validating prompt phrasing and expected output.
  2. If the same screenshot repeatedly appears (or if you’re processing many items), switch to Files API file_id to avoid re-uploading.
  3. Use detail: "low" for fast triage, and only switch to high when you need fine-grained analysis.

Because deepseek-v4-flash-vision-exp consumes text + images in the same message, the model can align its interpretation with your exact task instructions instead of relying on a separate image-description step.


Closing thought: vision APIs reward disciplined input

The hidden skill with vision APIs is not “prompt engineering” in the abstract—it’s input engineering. Once you treat images like a resource with limits (size caps, token caps, resizing behavior), the system becomes predictable. And predictability is what turns vision from a demo into something you can ship.

The block-based content format, the three image delivery paths, and the image token cap around an 800×800 equivalent are the pieces that make deepseek-v4-flash-vision-exp feel less like magic and more like a real building block.

ahsan

ahsan

Hello! I am Mr Ahsan, the writer of the Website. I am from Netherland. I like to write about technology and the news around it.

Comments (0)

No comments yet. Be the first to respond!

Leave a Comment

Your comment will be visible after review.