Vision and Multimodal AI
Process images, extract document data, and analyze visual diagrams using OpenAI and Claude multimodal Vision APIs.
TL;DR
- Encode local raster images into base64
data:image/jpegpayload strings. - Pass multi-image comparisons into
messagesarrays using content blocks. - Extract structured JSON records directly from scanned documents with
zod.
Base64 & URL Image Payloads
Remote Image URL InputSend public HTTPS image URL to OpenAI Vision API.
import OpenAI from 'openai';
const client = new OpenAI();
const res = await client.chat.completions.create({
model: 'gpt-4o',
messages: [{
role: 'user',
content: [
{ type: 'text', text: 'Describe this chart.' },
{
type: 'image_url',
image_url: {
url: 'https://example.com/c.png',
},
},
],
}],
});Local File Base64 EncoderRead local image buffer and format as base64 data URI.
import fs from 'node:fs';
function encodeImage(filePath: string) {
const buf = fs.readFileSync(filePath);
const b64 = buf.toString('base64');
return `data:image/jpeg;base64,${b64}`;
}Low vs High Detail ModeToggle image resolution mode to optimize cost and latency.
// low: 85 tokens flat cost, fast triage
// high: detailed tiles, reads dense text
const imageBlock = {
type: 'image_url' as const,
image_url: { url: dataUri, detail: 'low' as const },
};Claude Multimodal Messages
Claude Image Content BlockPass raw base64 data to Anthropic Messages API.
import Anthropic from '@anthropic-ai/sdk';
const anthropic = new Anthropic();
const r = await anthropic.messages.create({
model: 'claude-3-5-sonnet-20241022',
max_tokens: 1000,
messages: [{
role: 'user',
content: [
{
type: 'image',
source: {
type: 'base64',
media_type: 'image/jpeg',
data: base64Data,
},
},
{ type: 'text', text: 'Extract invoice total.' },
],
}],
});Multi-Image ComparisonCompare two consecutive UI screenshots in a single prompt.
const blocks = [
{ type: 'image', source: img1 },
{ type: 'image', source: img2 },
{ type: 'text', text: 'List visual diffs.' },
];Supported Image Media TypesAllowed mime types for Anthropic Vision requests.
type AllowedMime =
| 'image/jpeg'
| 'image/png'
| 'image/gif'
| 'image/webp';Visual Document & OCR Extraction
Structured Receipt ExtractionExtract typed JSON schema fields from receipt photos.
const receiptPrompt = [
{ type: 'text', text: 'Extract receipt into JSON.' },
{ type: 'image_url', image_url: { url: imgUri } },
];
const out = await client.chat.completions.create({
model: 'gpt-4o',
messages: [{
role: 'user',
content: receiptPrompt as any,
}],
response_format: { type: 'json_object' },
});Chart & Diagram Data Table ParserConvert visual line chart into structured CSV rows.
const chartPrompt = 'Extract all series data points ' +
'from this graph as CSV format with columns: x,y';
const payload = [
{ type: 'text', text: chartPrompt },
{ type: 'image_url', image_url: { url: chartUri } },
];Image Sanitization & Dimension CheckEnsure image dimensions fit within provider bounds.
function validateImageBounds(w: number, h: number) {
const maxDim = 8000;
if (w > maxDim || h > maxDim) {
throw new Error('Image exceeds 8000px maximum');
}
}Multimodal Performance & Optimization
Dynamic Image DownscalingResize large images using Sharp prior to base64 encoding.
import sharp from 'sharp';
async function prepImage(buffer: Buffer) {
return await sharp(buffer)
.resize(1600, 1600, { fit: 'inside' })
.jpeg({ quality: 80 })
.toBuffer();
}Vision Token Calculation FormulaEstimate token footprint for high-resolution images.
function estimateVisionTokens(w: number, h: number) {
const tilesX = Math.ceil(w / 512);
const tilesY = Math.ceil(h / 512);
return tilesX * tilesY * 170 + 85;
}Caching Multimodal PromptsMark static reference images with prompt cache breakpoints.
const cachedImg = {
type: 'image',
source: imgSource,
cache_control: { type: 'ephemeral' },
};Tips
- Downscale high-resolution images to under 2000 pixels with
sharpbefore base64 encoding to reduce token billing by up to sixty percent. - Combine explicit OCR text instructions with structured
response_formatschemas to guarantee flawless table extraction from image invoices.
Warnings
- Never send raw uncompressed PNG image buffers directly over the wire without validating upload size under provider
20MBlimits. - Avoid using multimodal models for fine-grained coordinate bounding without running specialized post-processing object
detectionalgorithms.
In Practice
Sends a base64 encoded document image to GPT-4o and extracts typed structured invoice fields.
- Prepare local image file as base64 data URI string.
- Assemble multimodal user message with text and image blocks.
- Dispatch completion request with json_object response format.
- Parse output JSON into validated business domain objects.
import OpenAI from 'openai';
const client = new OpenAI();
async function parseInvoice(b64: string) {
const uri = `data:image/jpeg;base64,${b64}`;
const res = await client.chat.completions.create({
model: 'gpt-4o',
messages: [{
role: 'user',
content: [
{ type: 'text', text: 'Extract total JSON.' },
{ type: 'image_url', image_url: { url: uri } },
],
}],
response_format: { type: 'json_object' },
});
return JSON.parse(res.choices[0].message.content!);
}
console.log(await parseInvoice('aW1hZ2VkYXRh...'));FAQ
Models split images into tiles of 512x512 pixels. Each tile consumes a fixed quantity of tokens plus a baseline overhead, making image dimensions directly proportional to cost.
Public HTTPS URLs reduce client payload bandwidth, but base64 strings are required for private, local, or authenticated assets behind firewalls.
Frontier models can read skewed or sideways text, but preprocessing images with auto-rotation orientation significantly improves extraction accuracy.