How to Calculate the Cost of a Vision Request with Images and Text
Vision request costs depend on tokens, pixels, frames, OCR, retries, and provider billing units, not file size alone.

A vision feature rarely makes a product expensive because of one image. Costs usually grow in other ways: the team sends photos at their original resolution, resends them in every turn, adds every video frame «just in case», and then tries to explain the finance bill using the average request price.
The cost of a vision request should be calculated as a composite expense, not as the price of a file. An image becomes tokens or a separate billing unit, the text beside it remains text, and the model response has its own price. OCR, search, image generation, and retries may also appear as separate line items. A useful budget model shows what changes when a photo becomes twice as large, a video produces more frames, or a user asks the system to «read everything in the fine print».
File price and image-understanding price are different
The size of a JPEG in megabytes says very little about analysis cost. It affects network transfer, request-body limits, upload time, and technical-log volume. The provider usually decodes the image, may resize it, split it into regions, or convert it into an internal representation, then bills for tokens, images, megapixels, or fixed quality tiers.
This distinction is often missed during design. A team reduces JPEG quality from 90 to 60, sees the file become smaller on disk, and expects the same API savings. If width and height remain unchanged, the internal billing method may not change at all. Conversely, reducing the long side from 4000 to 1600 pixels usually changes usage more noticeably, even if compression is imperfect.
For every image, store four values:
- width and height after all transformations;
- format and size of the transmitted file;
- selected detail or quality mode;
- actual usage from the provider response.
The first three explain expected usage before sending. The fourth prevents guesswork after launch.
Google Gemini documentation treats images as tokenized input alongside text and other modalities. Anthropic Vision documentation gives an approximation for images that do not need resizing: token count is roughly width multiplied by height and divided by 750. This is a useful engineering estimate, but it is not a universal formula. Do not transfer it to another API and present it as an exact bill.
Separate costs into five buckets first
A budget becomes understandable when every line item has its own bucket. Do not reduce everything to «request price».
The estimate for one call can be written as:
C = C_text_in + C_image + C_text_out + C_tools + C_transport + C_retry
Here, C_text_in includes the system instruction, user text, conversation history, and tool results if they are returned to the model. C_image covers images, pages, and frames. C_text_out includes the response, including JSON, explanations, and reasoning if the selected model bills it as output. C_tools covers paid OCR, web search, image generation, and other server-side actions. C_transport is usually outside the LLM bill, but belongs in your budget for storage, outbound traffic, and logs. C_retry reflects retries caused by timeouts, validation errors, rate limits, and uncertain results.
For a monthly forecast, do not multiply one average price by the number of calls. Use a distribution of request classes:
C_month = Σ (N_class × C_class) + C_fixed
For example, a product-card checking service may have four classes: one photo without text, one photo with small labeling, several product angles, and a document requiring OCR. Each class has different resolution, response length, retry probability, and model route. The average hides the most expensive class, even though that class may consume the budget at the end of the month.
C_fixed includes queues, storage, monitoring, proxies, image preparation, and the team’s work on error analysis. At low volume, these costs may exceed token charges. At high volume, they usually become smaller than API costs, but they do not disappear.
Choose resolution based on the smallest important object
High resolution is justified only when the task depends on details that disappear after resizing. A bill with small amounts, a serial number, a medicine label, and a device seal need one approach. Determining whether a photo contains a helmet or a car needs another.
A common bad pattern is a mobile app uploading a 4032×3024 photo because that is what the camera produced. The server forwards it unchanged even though the model only needs to identify the product type. The pixel count is roughly ten times higher than for 1280×960. With tokenization close to proportional to area, the bill grows almost in the same proportion while classification accuracy changes little.
A practical rule is to identify the smallest visual object the model must read or distinguish. Then choose a size that leaves that object with enough pixels after resizing. Text needs sufficient letter height, a barcode needs sharp contrast, and a defect needs enough pixels to be visible. The overall photo size is secondary.
Build a set of real difficult cases: glare, tilt, small print, poor cameras, and partially covered labels. Run it in three modes, such as original size, working resize, and aggressive resize. Compare task metrics rather than your impression of the answer: correctly extracted fields, classification accuracy, or defect-detection recall.
Then tie size to task class:
| Class | What to send | What to control |
|---|---|---|
| Rough classification | A reduced full scene | Whether major features remain visible |
| Field OCR | The page or a text crop | Character height and digit readability |
| Quality check | Region of interest plus overview | Whether the defect and its context are visible |
| Product comparison | Consistently prepared angles | Consistent object scale |
Cropping often saves more than compression. Do not remove context that changes meaning. A price tag without the product name, a document fragment without its heading, or part of a display without measurement units may make the model confidently invent a connection that is not in the frame.
Text beside the image can cost more than expected
Teams usually watch the image and forget the text tail. In production, photos quickly acquire system instructions, JSON Schema, conversation history, extraction rules, product catalogs, previous checks, and descriptions of available tools. The image then stops being the main expense.
A particularly costly case appears in multi-turn chats. The user sends a receipt, the system returns a short answer, the user asks a follow-up, and the application sends the original image, the entire previous conversation, and a long response schema again. After several turns, you pay for the same visual information repeatedly.
Separate initial perception from later discussion. On the first turn, give the model the image and request a compact structured result. On later turns, pass that result, the source identifier, and only the fragments needed for the new question.
Example of an internal object after the first analysis:
{
"asset_id": "receipt_8f2c",
"transform_version": "resize-1600-v3",
"vision_result": {
"merchant": "...",
"date": "...",
"total": "...",
"currency": "...",
"uncertain_fields": ["merchant"]
},
"needs_original_image": false
}
This object does not replace the original image forever. It prevents automatic resubmission. If the user asks about a hard-to-read line, the system can open the original, crop that line, and make a separate expensive request. That is more honest than paying for the entire frame on every turn «just in case».
Prompt caching also requires careful calculation. It helps when a large text prefix repeats: instructions, rules, a schema, and a stable reference catalog. Do not assume caching makes images or history free unless the provider explicitly includes them in cacheable usage. Check response fields and the documentation for the selected model.
OCR and vision solve different parts of the task
The advice to «always use an LLM for OCR» is popular because one call seems simpler: image in, JSON out. That is convenient for a demo. For streams of invoices, forms, waybills, and medical documents, it often adds cost and reduces control.
OCR answers which characters appear on the page and where they are located. A vision model answers broader questions: what is shown, which fields belong together, what looks suspicious, how to interpret an exception, and what to tell a person. These tasks overlap, but they are not identical.
A practical document pipeline is:
- Prepare the page: rotate it, remove blank margins, limit the maximum size, and save the transformation version.
- Run specialized OCR or built-in document parsing when it is needed for high-volume text extraction.
- Send the extracted text, field geometry, and only the crops where OCR is uncertain or visual context is needed to the LLM.
- Send records that violate rules or have low confidence for manual review.
This pipeline has two advantages. You can measure recognition error separately from interpretation error, and most pages do not need an expensive multimodal call on the full image.
Sometimes the full page is needed immediately. Stamps, signatures, unusual layouts, complex tables, handwritten notes, document substitution, and visual product matching require the image itself. Even then, «the page is needed» does not mean «the original camera resolution is needed».
Account separately for PDFs. A text PDF may provide extractable text without rendering every page visually. A scanned PDF is more likely to become a set of images and require OCR. Some platforms bill document pages under rules similar to images. Gemini documentation, for example, counts DOCUMENT modality tokens for PDFs at the image-token rate. Treat PDFs as their own cost class instead of hiding them among ordinary images.
Count video by frames, not file duration
A vision model does not receive «video» as a magical whole. Depending on the API, it sees sampled frames, an internal video representation, or a sequence of images. Duration in seconds alone therefore does not determine price. A budget needs the sampling rate, resolution per frame, number of passes, and the condition that ends processing.
The most expensive mistake is decoding an entire video into one frame every few hundred milliseconds and sending them all in one batch. If the task is «find the moment when an employee puts a box on the conveyor», you do not need a frame-by-frame reconstruction of every second.
First define the event. Then choose a sampling strategy:
- sparse uniform sampling to find the area of interest;
- denser frames only inside the identified time window;
- stop after confident event detection;
- a separate path for videos where the model is uncertain.
Suppose a camera records a ten-minute video. The first pass takes one frame every five seconds. If the model finds a likely segment, the second pass analyzes only the minute around it at a higher rate. This is not optimization for its own sake. It avoids paying for detailed analysis of nine minutes where nothing happens.
For video quality-control tasks, first try inexpensive classical filters: motion detection, scene changes, brightness, blur, and object presence. They do not replace the model, but they remove empty, dark, and nearly identical frames. Otherwise, you buy the same answer repeatedly.
Do not guess the provider’s billing unit from the model name
The same model may have different prices with different providers, and one API may expose several types of pricing. You may encounter input and output tokens, a fixed image price, a megapixel price, resolution tiers, reference-image pricing, generation costs, and separate fees for server-side tools.
OpenRouter documentation for image generation shows why a normalizer is needed: endpoint data may contain billable, unit, cost_usd, and a rate variant for the resolution tier. The unit may be image, megapixel, or token. Image understanding also depends on the specific model and provider. Do not store only price_per_1m_tokens and assume it covers every route.
Create an explicit tariff-rules table inside billing:
{
"route": "vision-route-a",
"billing_unit": "input_token",
"input_rate": "provider tariff",
"output_rate": "provider tariff",
"image_policy": "reported_in_prompt_usage",
"detail_modes": ["low", "high"],
"effective_from": "provider price version"
}
For a route with a fixed image price, replace billing_unit with image and store the rate by resolution or quality. For a megapixel route, save the rounding rule. Rounding matters: 1.01 megapixels may be billed differently from 1.00, and your estimate must reflect that.
Do not hard-code rates into application code. Prices, model lines, and billing rules change. Tariff configuration should have a version and effective date, and each calculation in the log should reference that version. Then, months later, you can explain why the same scenario cost different amounts.
The budget formula needs an upper bound
A typical forecast without an upper bound looks good in a spreadsheet and fails under real traffic. A user sends ten images instead of one. Marketing enables a new document upload. The service starts retrying after timeouts. The model writes a response five times longer. Last month’s average price says nothing about the limit needed today.
For every request class, define three modes:
| Mode | What changes | Purpose |
|---|---|---|
| Typical | Median sizes and an ordinary response | Planned spending |
| Stressed | More images, high detail, one retry | Team reserve |
| Maximum | Product and API limits | Limits and abuse protection |
Use the same formula with different inputs. If the typical «document check» class contains one page, do not use the average between one and twenty pages. That produces a number describing neither a normal nor a risky request.
Use measured p90 values rather than article estimates for the budget model:
images_per_request = 2
image_tokens_per_image = measured_p90
text_input_tokens = measured_p90
text_output_tokens = response_cap
retry_rate = observed_retry_rate
request_cost = (
images_per_request * image_tokens_per_image * input_rate +
text_input_tokens * input_rate +
text_output_tokens * output_rate +
tool_cost
) * (1 + retry_rate)
Use p90, not the mean, for operational budgeting. The mean is useful for analytics. Capacity reserves and alerts need a value that can handle heavy but normal operation.
Limits belong in the product, not only in spreadsheets. Limit file count, total pixels, frame count, response length, retries, and cost per request. When a limit is reached, return a clear message or put the task in an asynchronous queue. Silently reducing an image until it becomes unreadable is worse: you save money but receive an incorrect result without a clear reason.
Usage from the response matters more than a presentation calculator
A calculator is useful before launch. After launch, the source of truth is the usage returned by the API together with your technical metadata. If the response does not provide enough detail, keep the estimate an estimate rather than creating false precision to six decimal places.
Normalize a usage event after every call. You do not have to store the entire prompt and image, especially in banking, healthcare, and government. Store what lets you reconstruct the calculation without exposing content.
{
"request_id": "req_01",
"tenant_id": "tenant_42",
"route": "vision-route-a",
"model": "selected-model",
"provider": "selected-provider",
"input_text_tokens": 812,
"input_image_tokens": 1540,
"output_tokens": 247,
"image_count": 2,
"frames_sampled": 0,
"source_pixels": 2419200,
"transform_version": "resize-1600-v3",
"attempt": 1,
"status": "success",
"tariff_version": "2026-07"
}
Fields depend on the API, so some values will occasionally be null. That is fine. What is not fine is mixing unknown token counts with zeroes. Zero means there was no usage. null means it was not observed.
Build reports across four dimensions: task class, route, image size, and retry reason. Within a few days, you will see what drives changes. The cause is usually not «AI prices went up», but a simple defect: a new client version stopped resizing photos, a queue retries successful calls after a broken connection, JSON responses became larger, or the team enabled an expensive mode for every task.
AI Router can be the place where these accounting rules live independently of the application SDK. An OpenAI-compatible API lets you change routes without rewriting the client, while audit logs and key-level rate limits help separate spending by team and workflow. This helps with budgeting only if you still record dimensions, task classes, and actual usage instead of looking at one combined bill.
Optimize after measuring quality, not before
The worst kind of vision optimization looks like this: the team reduces every image, crops fields, limits responses to ten tokens, and switches the workflow to a cheaper model without testing. The bill falls. Then the rate of misread amounts, missed defects, and manual corrections quietly rises. A month later, the API turns out to have been the cheapest part of the process.
First define the acceptable result for each class. For field extraction, this may be accuracy on critical fields. For product-photo checks, it may be the share of correctly accepted and rejected cards. For video, it may be the probability of finding an event in the required window. Then change one parameter at a time: resolution, frame count, response length, image count, or route.
Review cost and quality in one table. If reducing the long side cuts spending by 45 percent and the error rate rises only within an acceptable range, the decision is clear. If savings are a few percent but you need more operators, the decision is bad even if the API-cost chart looks better.
Do not start by choosing the cheapest model. Take one expensive request class, record actual usage, prepare a difficult test set, and prove that lower resolution, event-based frames, or OCR combined with selective vision analysis does not break the result. Then the budget stops being a guess and becomes an engineering constraint you can manage.
Frequently asked questions
What is included in the cost of a vision request?
The formula should include text input tokens, image tokens, output tokens, tool calls, and any separate provider billing units. Then add a retry coefficient and a reserve for a high-load scenario. The average cost of one request is almost never enough to approve a budget.
How do I choose image resolution for a vision API?
Start with the task class rather than the maximum resolution. A reduced image is usually enough for classification and rough extraction, while small text, barcodes, and table fields require a separate mode. Test quality on a labeled sample and pay for high detail only where it changes the result.
How many video frames should I send to a multimodal model?
One frame may be enough for a static scene or a simple presence check. For motion, first define the sampling rate and a stopping rule, such as ending analysis after the required state is detected. Sending an entire video as a sequence of frames without such a rule is usually expensive and rarely improves quality proportionally.
When is OCR more cost-effective than LLM image analysis?
OCR is not the same as general visual analysis. If you need document fields, amounts, or numbers, first measure the cost and accuracy of specialized OCR, then send the model only the text and crops where semantic verification is needed. The full page is necessary when layout, stamps, or visual relationships between fields matter.
Does base64 affect the cost of image processing?
It can. Base64 increases the HTTP body by roughly one third, affecting network usage, limits, and log-storage costs. Providers usually bill the decoded image or its internal representation rather than the base64 characters. Check the rules for the specific API, and do not use JSON size as a substitute for the number of vision tokens.
Which metrics are needed to control vision costs?
Track input and output tokens, the breakdown by modality, the selected detail level, file sizes, frame counts, model, provider, and attempt status. Without this data, finance will see the total bill, but the team will not be able to find what caused it to rise. Logs should contain technical metadata without the sensitive images themselves unless they are needed for debugging.
Is batch processing suitable for image workloads?
Yes, when the volume is known in advance and some delay is acceptable. Batch processing works well for archives, overnight document processing, and catalog reindexing, but not for interactive receipt checks in an app. A discount will not fix oversized images or unnecessary retries.
How can I avoid paying repeatedly for the same image in a chat?
Do not resend the same image in every chat message. Store the extraction result, transformation-version identifier, and a short structured context, then add the original only when a new visual task requires it. Prompt caching can reduce the cost of repeated text, but it should not be assumed to eliminate the cost of every image automatically.
How should I prepare a budget forecast for management?
Show three scenarios: typical, stressed, and the upper limit defined by your product and API limits. For each, list requests, images per request, dimensions, frames, text, expected output, retries, and the billing unit. Then convert the currency according to your company policy and separate API costs from storage, queues, and observability.
Do I need a gateway to manage vision costs?
An OpenAI-compatible gateway is useful when you want to keep your SDK and request format while adding unified tracking by model, provider, and key. AI Router lets you change the base URL to api.airouter.kz and continue using a compatible API. Teams in Kazakhstan can also use monthly B2B invoicing in tenge. The budget model still needs to be based on actual usage for each route.