Kimi K3 Vision Guide: Image Tokens, Video, API Code & Real Costs
September 25, 2026 · kimi k3 vision · kimi k3 image input · kimi k3 multimodal · kimi k3 video understanding · kimi k3 screenshot to code · kimi k3 api · moonvit · kimi k3 image tokens
Yes, Kimi K3 can see. It takes images and video through the same kimi-k3 API model you use for text, and it bills image tokens at the normal input rate. A typical 1080p screenshot costs about 2,700 input tokens, or under one cent uncached. The things that trip people up are practical ones: the API rejects public image URLs, K3’s mandatory thinking makes the answer cost more than the picture, and some tasks just don’t need vision at all.
This guide is current as of September 25, 2026. It covers what the official docs actually say, the image token math worked out from Moonshot’s own open-weight processor code, working API code, the vendor-reported benchmarks, and a candid list of where vision earns its keep and where it’s a waste of tokens.
What “native vision” means for K3
- Encoder: a 401M-parameter MoonViT-V2 vision tower, per the Kimi K3 model card on Hugging Face and the GitHub repo. A community extraction of the encoder weights (AI4Industry/MoonViT-V2) describes it as a 27-layer ViT with 14x14 patches, randomly initialized and trained jointly with the language model rather than starting from SigLIP.
- Inputs: text, images and video in one model, inside the same 1,048,576-token context window. Output is text only.
- Where it runs: the official API, the Kimi app and kimi.com, and most third-party hosts. OpenRouter’s model registry lists K3’s input modalities as
text,imageandvideo; Artificial Analysis lists text and image.
Moonshot’s launch material leans hard on one idea: “vision in the loop.” The Kimi K3 tech blog and the @Kimi_Moonshot launch thread describe K3 iterating between code and live screenshots: write the UI, render it, look at the result, fix it. The GitHub README extends that to “vision-in-the-loop game dev, CAD, and even chip design.” That’s the right mental model: K3’s vision is built for agents that check their own visual output.
For the full model specs (2.8T MoE, 104B active, MXFP4 weights), see the Kimi K3 specifications page.
The official limits, in one table
Everything below comes from Moonshot’s vision model guide, the Kimi K3 quickstart and the Files API reference.
| Item | What the docs say |
|---|---|
| Vision-capable models | kimi-k3, kimi-k2.6, kimi-k2.7-code, kimi-k2.7-code-highspeed |
| Image formats | JPEG, PNG, GIF, WebP, BMP, HEIC, HEIF |
| Video formats | MP4, MPEG, MOV, AVI, FLV, MPG, WebM, WMV, 3GPP |
| Not supported | SVG (send the SVG source as text instead) |
| Special case | Animated GIF/WebP may be processed as video, at video token cost |
| How to send | Base64 data URL, or upload and reference ms://<file-id> |
| Public image URLs | Not supported |
| Request body limit | 100M |
| Uploaded file limit | 100 MiB per file, 10 GiB default storage per organization |
| Recommended image size | Up to 4096x2160 (4K) |
| Recommended video size | Up to 1920x1080 (FHD) |
| Token counting | ”Dynamic”: depends on resolution and video keyframes |
| Works with | Multi-turn, streaming, tool calls, JSON Mode, Partial Mode |
Two details are easy to miss. First, the Files API no longer does text extraction on images. If you upload a screenshot with purpose="file-extract" you won’t get vision; you need purpose="image". Second, file-extract still exists for PDFs, Office files and code, and the docs say the parsing service is currently free. So for a text-heavy PDF you often have two routes: extract the text for free, or render the pages to images and pay vision tokens. More on choosing between them below.
How many tokens does an image cost?
Moonshot’s docs don’t publish a per-image token table. They say token counts are dynamic and point you to the estimate endpoint. But the open-weight release ships the actual preprocessing code, and it’s specific enough to do the math.
The preprocessor_config.json in the Hugging Face repo sets:
patch_size: 14andmerge_kernel_size: 2, so one visual token covers a 28x28 pixel blockin_patch_limit: 65536patches per image, which works out to a cap of about 16,400 tokens per imagepatch_limit_on_one_side: 512, so no side is processed at more than 7,168 pixels
The resize function in the repo’s media_utils.py scales an image down only when it exceeds those caps, then pads each side up to a multiple of 28. Running that exact function on common sizes gives:
| Image | Visual tokens | Cost at $3/M (cache miss) | Cost at $0.30/M (cache hit) |
|---|---|---|---|
| 512x512 icon or crop | 361 | $0.0011 | $0.0001 |
| 1024x768 | 1,036 | $0.0031 | $0.0003 |
| 1280x800 laptop screenshot | 1,334 | $0.0040 | $0.0004 |
| 1920x1080 full-HD screenshot | 2,691 | $0.0081 | $0.0008 |
| 1170x2532 phone screenshot | 3,822 | $0.0115 | $0.0011 |
| 2560x1440 monitor | 4,784 | $0.0144 | $0.0014 |
| 2550x3300 (letter page at 300 DPI) | 10,856 | $0.0326 | $0.0033 |
| 3840x2160 (4K) | 10,764 | $0.0323 | $0.0032 |
| 7680x4320 (8K, downscaled) | ~16,600 (cap) | ~$0.050 | ~$0.005 |
Treat this table as a well-grounded estimate, not an invoice. It’s derived from the open-weight processor. Moonshot’s hosted API could apply extra resizing or different limits, and it has not published its own figures. Before you run a batch job, check a few real inputs against the official token estimate endpoint (shown below). Also note that we have not seen Moonshot confirm whether image tokens get the $0.30 cache-hit rate when they sit in a reused prompt prefix. Its automatic caching is prefix-based, so it should work in principle, but check your usage logs rather than budgeting for it.
Two practical rules fall out of the math:
- Token cost scales with pixel area. Doubling both dimensions quadruples the tokens. A retina screenshot at 2880x1800 costs about 6,700 tokens. The same UI captured at 1440x900 costs about a quarter of that, and it’s usually just as readable.
- Crop before you scale. If the bug lives in one card, send that card. A 600x400 crop costs a few hundred tokens and gives the model fewer places to look.
One more detail from the config: transparent images are composited onto a gray-and-white chessboard pattern (8-pixel squares) before encoding. If you send a transparent PNG logo or icon, the model sees it on a checkerboard. That’s usually fine, but flatten it onto a solid background if the edge detail matters.
The bill is mostly the answer, not the image
Here’s the part most vision guides leave out. K3 always thinks. The quickstart says thinking mode can’t be disabled; you can only lower reasoning_effort from its default of max to high or low. Reasoning tokens bill as output at $15 per million, five times the input rate. And max_completion_tokens defaults to 131,072.
So a 1080p screenshot costs about $0.008 to send in, while 2,000 tokens of reasoning plus answer cost $0.03. In DataCamp’s hands-on tutorial, a single screenshot-debugging call with max_completion_tokens set to 3,500 came to about 2 cents. Most of that was output.
| Scenario (1080p screenshot + short prompt) | Input | Output | Approx. cost |
|---|---|---|---|
OCR or caption, reasoning_effort: low, ~500 output tokens | ~2,800 | ~500 | ~$0.016 |
| UI bug diagnosis, ~2,000 output tokens | ~2,800 | ~2,000 | ~$0.038 |
| Screenshot-to-component, ~6,000 output tokens | ~2,800 | ~6,000 | ~$0.098 |
Output token counts are illustrative, not measured. Prices are the official $3 input / $0.30 cached / $15 output from Moonshot’s pricing page, which is flat across the full context length.
The takeaway: shrinking images saves pennies; capping output saves dollars. For extraction-style jobs, set reasoning_effort: "low" and a sensible max_completion_tokens. Save max for design reasoning where the thinking actually helps.
API code: sending images and video
The API is OpenAI-compatible at https://api.moonshot.ai/v1, and K3 unlocks after a $1 top-up. The one rule that matters: content must be an array of parts, not a string. Here’s a two-image comparison, the pattern behind most visual regression checks:
import base64
import os
from pathlib import Path
from openai import OpenAI
client = OpenAI(
api_key=os.environ["MOONSHOT_API_KEY"],
base_url="https://api.moonshot.ai/v1",
)
def as_data_url(path: str) -> str:
ext = Path(path).suffix.lstrip(".").lower().replace("jpg", "jpeg")
b64 = base64.b64encode(Path(path).read_bytes()).decode()
return f"data:image/{ext};base64,{b64}"
resp = client.chat.completions.create(
model="kimi-k3",
reasoning_effort="high", # default is "max"
max_completion_tokens=4000, # default is 131,072
messages=[{
"role": "user",
"content": [
{"type": "text", "text": "Image 1 is the design. Image 2 is the build."},
{"type": "image_url", "image_url": {"url": as_data_url("design.png")}},
{"type": "image_url", "image_url": {"url": as_data_url("build.png")}},
{"type": "text", "text": "List every visual difference, then give a CSS fix for each."},
],
}],
)
print(resp.choices[0].message.content)
print(resp.usage) # check real prompt tokens here
Note that temperature (1.0), top_p (0.95) and the penalties are fixed on K3, so don’t bother tuning them.
For video, don’t base64 it. Upload the file with purpose="video" and pass the returned ID as an ms:// URL:
video = client.files.create(file=Path("repro.mp4"), purpose="video")
try:
resp = client.chat.completions.create(
model="kimi-k3",
messages=[{
"role": "user",
"content": [
{"type": "video_url", "video_url": {"url": f"ms://{video.id}"}},
{"type": "text", "text": "Write numbered repro steps for the bug shown, with timestamps."},
],
}],
)
print(resp.choices[0].message.content)
finally:
client.files.delete(video.id) # uploads count against your 10 GiB quota
To check token counts before you commit, the estimate endpoint takes the same model and messages body and returns data.total_tokens:
import requests
r = requests.post(
"https://api.moonshot.ai/v1/tokenizers/estimate-token-count",
headers={"Authorization": f"Bearer {os.environ['MOONSHOT_API_KEY']}"},
json={
"model": "kimi-k3",
"messages": [{"role": "user", "content": [
{"type": "image_url", "image_url": {"url": as_data_url("build.png")}},
{"type": "text", "text": "Describe this."},
]}],
},
)
print(r.json()["data"]["total_tokens"])
Third-party providers: most hosts in our Kimi K3 API providers guide accept OpenAI-style image_url parts, but video support and URL handling vary by host. The ms:// file scheme is specific to Moonshot’s own API. If your pipeline depends on video, confirm it with a test call on your provider before you migrate.
Vision benchmarks: where K3 leads and where it doesn’t
These are Moonshot’s own numbers from the Hugging Face model card. Where a cell shows two numbers, the model card footnote says they are scores without / with tool augmentation (Python tools for the vision tasks).
| Benchmark | Kimi K3 | Claude Fable 5 | GPT-5.6 Sol | Claude Opus 4.8 | GPT-5.5 |
|---|---|---|---|---|---|
| OmniDocBench (documents) | 91.1 | 89.8 | 85.8 | 87.9 | 89.4 |
| Video-MME, with subtitles | 90.0 | — | 89.5 | 86.0 | 89.3 |
| MMVU (video) | 82.1 | — | 81.2 | 79.2 | 81.7 |
| MMMU-Pro | 81.6 / 83.4 | 81.2 / 86.5 | 83.0 / 84.6 | 78.9 / 82.7 | 81.2 / 83.2 |
| CharXiv (reasoning) | 84.8 / 91.3 | 88.9 / 93.5 | 84.6 / 89.1 | 80.5 / 89.9 | 84.1 / 89.0 |
| MathVision | 94.3 / 97.8 | 94.8 / 98.6 | 95.8 / 97.8 | 86.7 / 97.1 | 92.2 / 96.8 |
| PerceptionBench (in-house) | 58.5 | 57.2 | 59.7 | 47.2 | 55.8 |
| WorldVQA ForceAnswer | 51.0 | 56.7 | 41.8 | 39.1 | 38.5 |
The model card also lists ZeroBench at 23.0 without tools and 41.0 with tools (pass@5), a reminder that the hardest visual puzzles are still far from solved for every model.
How to read this honestly:
- Documents and video are K3’s strongest showing. Leading OmniDocBench matters for anyone doing PDF, invoice or table extraction, and the video scores back up the “native multimodal” claim.
- Chart reasoning and world knowledge from images lag Claude Fable 5. CharXiv is 4 points behind without tools, and WorldVQA (recognizing real-world entities) is nearly 6 points behind.
- MMMU-Pro is effectively a tie without tools, within about 1.5 points across the top three.
- PerceptionBench is Moonshot’s in-house benchmark. Weight it accordingly.
None of these have been independently reproduced at scale yet, and vendor tables tend to flatter the vendor. For the wider head-to-heads, see Kimi K3 vs Claude Fable 5 and Kimi K3 vs GPT-5.6.
What independent tests found
Spot checks from outside Moonshot are small but useful:
- Puter’s visual diff test (Puter developer blog, July 20): they screenshotted a real homepage, introduced five CSS mistakes, and sent both images. K3 caught all five (a headline wrap, a button color change, an underline, widened icon spacing and a removed arrow icon) with no invented differences. It did misdescribe the original icon layout while correctly flagging that it changed. The authors call it “a spot check rather than a benchmark.”
- DataCamp’s dashboard test (DataCamp, July 21): K3 found an overlapping card, a badge covering a number, uneven spacing, a chart overflowing its card and a misplaced tooltip, and suggested moving the cards into one grid. It misread a partly hidden “3,910” as “5,910” and missed a nearly invisible low-contrast subtitle entirely.
- Mem0’s vision coding agent (Mem0 blog): in a screenshot-driven UI loop, regressions appeared in 3 of 5 runs without persistent memory and 0 of 5 with it. That says as much about harness design as about the model.
The pattern: K3 is strong at spotting what changed or broke in a UI, and weaker at subtle, low-contrast or occluded detail.
When vision wins, and when text is better
| Task | Use vision? | Why |
|---|---|---|
| CSS/layout bugs, visual regressions | Yes | The bug is visual; the DOM doesn’t show overlap or clipping |
| Design mockup to component scaffold | Yes | Faster than describing a layout in words |
| Screen recording of a bug (short clip) | Yes | Video captures timing and state changes a log misses |
| Scanned PDFs, photos of receipts, whiteboards | Yes | There is no text layer to extract |
| Charts where you have the underlying data | No | Send the CSV; text is exact, charts get misread |
| Digital PDFs with a text layer | Usually no | file-extract parsing is free and exact; use vision only for layout-heavy pages |
| SVG logos and icons | No | SVG isn’t supported as an image; the source text is smaller anyway |
| Backend, SQL, algorithm work | No | Nothing visual to see |
| Accessibility audits | Partly | A screenshot can’t show focus order, ARIA or semantic HTML |
| Long marketing videos as context | Rarely | Trim to the seconds that matter; tokens scale with keyframes |
The accessibility point comes from a sharp DEV Community discussion: vision models don’t see the DOM, so they can’t judge keyboard focus or semantic markup. Pair screenshots with the relevant HTML when accessibility matters.
For coding agents specifically, the sweet spot is a loop: the agent edits code, a headless browser screenshots the result, and K3 compares it with the target. That’s what Kimi Code and similar harnesses are built around.
Limitations and gotchas
- No public URLs. Passing
https://.../image.pngfails on Moonshot’s API. Download and base64 it, or upload it. - Stringified content breaks vision. If
contentis a JSON string instead of an array of parts, the images never reach the model. - Always-on thinking adds latency. Artificial Analysis measures K3 (max) at about 35 output tokens per second with a 3.8-second time to first token. A vision call that writes 3,000 reasoning tokens takes well over a minute. Lower
reasoning_effortfor interactive tools. - Text only out. K3 can’t edit or generate images. It writes code (HTML, CSS, SVG, canvas) that renders them.
- Prompt injection through pixels. A screenshot can carry hidden instructions, such as white text on a white background. Treat image content from untrusted sources like untrusted text.
- Self-hosting vision adds complexity. The open weights include the vision tower (it’s kept out of MXFP4 quantization per the config), and vLLM and SGLang are the recommended engines. But you still need the same ~1.7TB-class serving setup covered in our VRAM requirements guide. Vision is not a reason to self-host.
FAQ
Can Kimi K3 read images and video? Yes. Kimi K3 is natively multimodal: the same model accepts text, images and video through the kimi-k3 API model, using a 401M-parameter MoonViT-V2 vision encoder that was trained jointly with the language model. Output is text only. It cannot generate images or video.
How many tokens does an image cost in Kimi K3? Roughly one token per 28x28 pixel block. Using the resize logic in Moonshot’s open-weight processor, a 1920x1080 screenshot comes to about 2,691 tokens, a 1280x800 screenshot about 1,334, and a 4K frame about 10,764. A single image is capped at roughly 16,400 tokens. Moonshot does not publish a per-image table, so use the estimate-token-count endpoint to confirm on the hosted API.
How much does it cost to send a screenshot to Kimi K3? Image tokens bill at the normal input rate: $3 per million on a cache miss and $0.30 on a cache hit. A 1080p screenshot is therefore about $0.008 uncached. The bigger cost is usually the answer, because K3 always thinks and output is $15 per million tokens. DataCamp’s screenshot-debugging test came to about 2 cents per call.
Does the Kimi K3 API accept image URLs?
No. Moonshot’s vision docs state that public image URLs are not supported. Send images as base64 data URLs inside an image_url content part, or upload them with the Files API (purpose image or video) and reference them as ms://
What image and video formats does Kimi K3 support? Images: JPEG, PNG, GIF, WebP, BMP, HEIC and HEIF. Video: MP4, MPEG, MOV, AVI, FLV, MPG, WebM, WMV and 3GPP. SVG is not supported as an image, so send SVG source as text. Animated GIFs and WebPs may be processed as video and billed at video token rates.
Is Kimi K3 better at vision than GPT-5.6 or Claude Fable 5? It depends on the task. On Moonshot’s own model card, K3 leads on OmniDocBench (91.1) and Video-MME with subtitles (90.0), roughly ties on MMMU-Pro, and trails Claude Fable 5 on CharXiv reasoning and WorldVQA. These are vendor-reported numbers, so treat them as directional until independent evaluations catch up.
What are the size limits for Kimi K3 image input? The whole request body can be up to 100M, and uploaded files up to 100 MiB each. Moonshot recommends images no larger than 4096x2160 and video no larger than 1920x1080, because higher resolutions add processing time and tokens without improving understanding.
Can I turn off Kimi K3’s thinking to make vision calls cheaper? No. K3 always runs with thinking enabled. You can lower reasoning_effort from the default max to high or low, and cap max_completion_tokens (default 131,072), which is the most effective way to keep simple OCR or captioning calls cheap.
The bottom line
Kimi K3’s vision is real, cheap to feed and built for agents that check their own work. A full-HD screenshot costs about 2,700 input tokens, less than a cent. Documents and video are its strongest benchmark areas, and independent spot checks show it reliably catches visible UI breakage. Its weak spots are subtle, low-contrast or occluded detail, chart reasoning where Claude Fable 5 still leads, and latency from thinking you can’t turn off.
Use it for layout bugs, design-to-code, scanned documents and short bug recordings. Skip it when a text source exists: CSVs beat charts, text layers beat page renders, and SVG source beats a picture of a logo. Base64 everything, crop before you send, and cap output, because that’s where the money goes.
Keep reading: where to run it in our API providers comparison, what the open weights include, and how to wire K3 into a coding loop with Kimi Code.