Multi-Image Comparison
On this page
Analyze Multiple Images in a Single Request
One of Grok Vision’s key strengths is the ability to send an unlimited number of images in a single request. This opens up unique possibilities for comparison, temporal tracking, and cross-analysis that single-image APIs cannot offer.
Multi-Image Request Structure
The format is simple: add as many input_image objects as needed to the input array, interleaving them with text to guide the analysis:
response = client.responses.create(
model="grok-4.5",
input=[
{"type": "input_text", "text": "Image A:"},
{"type": "input_image", "image_url": url_image_a},
{"type": "input_text", "text": "Image B:"},
{"type": "input_image", "image_url": url_image_b},
{"type": "input_text", "text": "Compare these two images in detail."}
]
)
Labeling each image with text (“Image A”, “Image B”) helps the model structure its response and clearly reference each image.
Use Case: Before/After Comparison
Ideal for project tracking, renovation, design, or quality control:
def comparer_avant_apres(url_avant, url_apres):
prompt = """Compare these two images (before and after) and identify:
1. The main changes
2. Elements that have not changed
3. Visible improvements
4. Any potential issues introduced
Present your response as a structured list."""
response = client.responses.create(
model="grok-4.5",
input=[
{"type": "input_text", "text": "BEFORE:"},
{"type": "input_image", "image_url": url_avant, "detail": "high"},
{"type": "input_text", "text": "AFTER:"},
{"type": "input_image", "image_url": url_apres, "detail": "high"},
{"type": "input_text", "text": prompt}
],
store=False
)
return response.output_text
Use Case: Temporal Tracking
Track the evolution of a location, product, or process over time:
def analyser_evolution(images_chronologiques):
"""images_chronologiques: list of {"url": ..., "date": ...}"""
input_data = []
for img in images_chronologiques:
input_data.append({
"type": "input_text",
"text": f"Photo from {img['date']}:"
})
input_data.append({
"type": "input_image",
"image_url": img["url"],
"detail": "auto"
})
input_data.append({
"type": "input_text",
"text": """Analyze the chronological evolution visible in
these images. Identify progressive changes, trends,
and any notable events between the different dates."""
})
response = client.responses.create(
model="grok-4.5",
input=input_data,
store=False
)
return response.output_text
Use Case: Quality Control
Compare a manufactured product to its reference model:
def controle_qualite(url_reference, url_produit):
prompt = """Compare the photographed product to the reference model.
Identify:
1. Compliance (what matches the model)
2. Non-compliance (deviations, defects, differences)
3. Severity of each non-compliance (minor, major, critical)
Return a JSON with:
{
"compliant": true/false,
"score": 0-100,
"compliances": [...],
"non_compliances": [
{"description": "...", "severity": "minor|major|critical"}
]
}"""
response = client.responses.create(
model="grok-4.5",
input=[
{"type": "input_text", "text": "REFERENCE (expected model):"},
{"type": "input_image", "image_url": url_reference, "detail": "high"},
{"type": "input_text", "text": "PRODUCT to check:"},
{"type": "input_image", "image_url": url_produit, "detail": "high"},
{"type": "input_text", "text": prompt}
],
store=False
)
return response.output_text
Use Case: Competitive Analysis
Compare interfaces, packaging, or product presentations from competitors:
def analyser_concurrence(images_concurrents):
"""images_concurrents: [{"brand": "...", "url": "..."}]"""
input_data = []
for concurrent in images_concurrents:
input_data.append({
"type": "input_text",
"text": f"{concurrent['brand']}:"
})
input_data.append({
"type": "input_image",
"image_url": concurrent["url"],
"detail": "auto"
})
input_data.append({
"type": "input_text",
"text": """Compare these competitor products/interfaces.
For each, identify visual strengths and weaknesses.
Provide a positioning recommendation."""
})
response = client.responses.create(
model="grok-4.5",
input=input_data,
store=False
)
return response.output_text
Optimizing Multi-Image Requests
When you send many images, token consumption increases rapidly. Here are a few optimization strategies:
Adjust the Detail Level
Use low for general comparisons and high only when analyzing fine details:
# Global comparison: low is sufficient
detail = "low" # ~256 tokens per image
# Defect analysis: high required
detail = "high" # ~1024-1792 tokens per image
Limit the Number of Images per Request
Even though there is no hard limit, with more than 10-15 images the analysis quality may decrease. The model has a finite context and must distribute it across all images:
# If more than 10 images, process in batches
def analyser_par_lots(images, taille_lot=10):
resultats = []
for i in range(0, len(images), taille_lot):
lot = images[i:i + taille_lot]
resultat = analyser_lot(lot)
resultats.append(resultat)
return fusionner_resultats(resultats)
Resize Images
If you are comparing high-resolution photos for general analysis, resize them before sending to reduce tokens:
def preparer_pour_comparaison(chemin, taille_max=(800, 800)):
img = Image.open(chemin)
img.thumbnail(taille_max)
# ... encode to base64
Key Takeaways
- The number of images per request is unlimited — this is a key advantage of the xAI API
- Label each image with text to structure the analysis
- Adjust the
detailparameter to the type of comparison - Beyond 10-15 images, process in batches to maintain quality
- Use cases include: before/after, temporal tracking, quality control, competitive analysis