Batch Image Processing (legacy)
Process multiple images in a single request. This endpoint is for images only - for multi-page documents use document processing instead.
v3/batch accepts images only. It cannot process PDFs or any other document, and submitting one will not work.
We do not recommend it for new integrations. Existing batch integrations keep working. For many images, use v3/text with the async flag and a tags field. For documents, use v3/pdf, or files/v1 at bulk volumes.
Mathpix has two distinct batch endpoints:
POST /v3/batch(this page) - batch of images for OCR; submit, then retrieve results by pollingGET /v3/batch/{batch_id}.POST /files/v1/jobs- high-throughput, large-scale batch of documents (PDFs, etc.) for large-scale processing. See the Files API Quickstart.
Only use the batch API when your workload is not latency sensitive. For immediate responses use single image endpoints.
Workflow
- Submit a batch of image URLs - returns a
batch_id - Poll results with
GET /v3/batch/{batch_id}(wait ~1 second per 5 images) - Results contain an OCR result object for each image key
Submit a batch
Submit a set of image URLs to the v3/batch endpoint:
- cURL
- Python
- JavaScript / TypeScript
- Go
- Java
curl -X POST https://api.mathpix.com/v3/batch \
-H "app_id: APP_ID" \
-H "app_key: APP_KEY" \
-H "Content-Type: application/json" \
--data '{
"urls": {
"inverted": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/inverted.jpg",
"algebra": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/algebra.jpg"
},
"formats": ["latex_simplified"]
}'
import requests
base_url = "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/"
r = requests.post("https://api.mathpix.com/v3/batch",
json={
"urls": {
"algebra": base_url + "algebra.jpg",
"inverted": base_url + "inverted.jpg"
},
"formats": ["latex_simplified"]
},
headers={
"app_id": "APP_ID",
"app_key": "APP_KEY",
"content-type": "application/json"
},
timeout=30
)
reply = r.json()
print(reply) # {"batch_id": 17}
const base = "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/";
const response = await fetch("https://api.mathpix.com/v3/batch", {
method: "POST",
headers: {
app_id: "APP_ID",
app_key: "APP_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
urls: {
inverted: base + "inverted.jpg",
algebra: base + "algebra.jpg",
},
formats: ["latex_simplified"],
}),
});
const { batch_id } = await response.json();
console.log(`Batch ID: ${batch_id}`);
body := bytes.NewBufferString(`{
"urls": {
"inverted": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/inverted.jpg",
"algebra": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/algebra.jpg"
},
"formats": ["latex_simplified"]
}`)
req, _ := http.NewRequest("POST", "https://api.mathpix.com/v3/batch", body)
req.Header.Set("app_id", "APP_ID")
req.Header.Set("app_key", "APP_KEY")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
result, _ := io.ReadAll(resp.Body)
fmt.Println(string(result)) // {"batch_id": 17}
HttpClient client = HttpClient.newHttpClient();
String body = """
{
"urls": {
"inverted": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/inverted.jpg",
"algebra": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/algebra.jpg"
},
"formats": ["latex_simplified"]
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.mathpix.com/v3/batch"))
.header("app_id", "APP_ID")
.header("app_key", "APP_KEY")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
{
"batch_id": 17
}
Use the batch_id to poll for results.
Poll for results
Wait approximately one second per five images, then poll GET v3/batch/{batch_id} for results:
- cURL
- Python
- JavaScript / TypeScript
- Go
- Java
curl https://api.mathpix.com/v3/batch/17 \
-H "app_id: APP_ID" \
-H "app_key: APP_KEY"
import requests, time
headers = {"app_id": "APP_ID", "app_key": "APP_KEY"}
batch_id = "17"
time.sleep(5) # wait for processing
r = requests.get(f"https://api.mathpix.com/v3/batch/{batch_id}", headers=headers)
print(r.json())
const headers = { app_id: "APP_ID", app_key: "APP_KEY" };
const batchId = "17";
await new Promise((r) => setTimeout(r, 5000));
const response = await fetch(`https://api.mathpix.com/v3/batch/${batchId}`, { headers });
console.log(await response.json());
time.Sleep(5 * time.Second)
req, _ := http.NewRequest("GET", "https://api.mathpix.com/v3/batch/17", nil)
req.Header.Set("app_id", "APP_ID")
req.Header.Set("app_key", "APP_KEY")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
result, _ := io.ReadAll(resp.Body)
fmt.Println(string(result))
HttpClient client = HttpClient.newHttpClient();
Thread.sleep(5000);
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.mathpix.com/v3/batch/17"))
.header("app_id", "APP_ID").header("app_key", "APP_KEY").GET().build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Before completion, results may be empty or partial. When complete:
{
"keys": ["algebra", "inverted"],
"results": {
"algebra": {
"detection_list": [],
"detection_map": {
"contains_chart": 0,
"contains_diagram": 0,
"contains_graph": 0,
"contains_table": 0,
"is_blank": 0,
"is_inverted": 0,
"is_not_math": 0,
"is_printed": 0
},
"latex_simplified": "12 + 5 x - 8 = 12 x - 10",
"latex_confidence": 0.99640350138238,
"position": {
"height": 208,
"top_left_x": 0,
"top_left_y": 0,
"width": 1380
}
},
"inverted": {
"detection_list": ["is_inverted", "is_printed"],
"latex_simplified": "x ^ { 2 } + y ^ { 2 } = 9",
"latex_confidence": 0.99982263230866
}
}
}
For this example response, each key in results contains a latex_simplified field with the recognized LaTeX. The algebra result renders as:
The inverted result renders as:
Use v3/text behavior
Set the ocr_behavior request parameter to "text" to process images with v3/text behavior instead of the default v3/latex. Options can be set at the top level or per image.
Top-level options
- Request body
- cURL
- Python
- JavaScript / TypeScript
- Go
- Java
{
"urls": {
"inverted": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/inverted.jpg",
"algebra": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/algebra.jpg"
},
"ocr_behavior": "text",
"formats": ["text", "html", "data"],
"data_options": { "include_asciimath": true }
}
curl -X POST https://api.mathpix.com/v3/batch \
-H "app_id: APP_ID" \
-H "app_key: APP_KEY" \
-H "Content-Type: application/json" \
--data '{
"urls": {
"inverted": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/inverted.jpg",
"algebra": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/algebra.jpg"
},
"ocr_behavior": "text",
"formats": ["text", "html", "data"],
"data_options": {"include_asciimath": true}
}'
import requests
base_url = "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/"
r = requests.post("https://api.mathpix.com/v3/batch",
json={
"urls": {
"inverted": base_url + "inverted.jpg",
"algebra": base_url + "algebra.jpg"
},
"ocr_behavior": "text",
"formats": ["text", "html", "data"],
"data_options": {"include_asciimath": True}
},
headers={
"app_id": "APP_ID",
"app_key": "APP_KEY",
"content-type": "application/json"
}
)
print(r.json())
const base = "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/";
const response = await fetch("https://api.mathpix.com/v3/batch", {
method: "POST",
headers: {
app_id: "APP_ID",
app_key: "APP_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
urls: {
inverted: base + "inverted.jpg",
algebra: base + "algebra.jpg",
},
ocr_behavior: "text",
formats: ["text", "html", "data"],
data_options: { include_asciimath: true },
}),
});
const { batch_id } = await response.json();
console.log(`Batch ID: ${batch_id}`);
body := bytes.NewBufferString(`{
"urls": {
"inverted": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/inverted.jpg",
"algebra": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/algebra.jpg"
},
"ocr_behavior": "text",
"formats": ["text", "html", "data"],
"data_options": {"include_asciimath": true}
}`)
req, _ := http.NewRequest("POST", "https://api.mathpix.com/v3/batch", body)
req.Header.Set("app_id", "APP_ID")
req.Header.Set("app_key", "APP_KEY")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
result, _ := io.ReadAll(resp.Body)
fmt.Println(string(result))
HttpClient client = HttpClient.newHttpClient();
String body = """
{
"urls": {
"inverted": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/inverted.jpg",
"algebra": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/algebra.jpg"
},
"ocr_behavior": "text",
"formats": ["text", "html", "data"],
"data_options": { "include_asciimath": true }
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.mathpix.com/v3/batch"))
.header("app_id", "APP_ID")
.header("app_key", "APP_KEY")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Per-image options
- Request body
- cURL
- Python
- JavaScript / TypeScript
- Go
- Java
{
"urls": {
"inverted": {
"url": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/inverted.jpg",
"ocr_behavior": "text",
"formats": ["text", "html", "data"],
"data_options": { "include_asciimath": true }
},
"algebra": {
"url": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/algebra.jpg",
"ocr_behavior": "text",
"formats": ["text", "html", "data"],
"data_options": { "include_asciimath": true }
}
}
}
curl -X POST https://api.mathpix.com/v3/batch \
-H "app_id: APP_ID" \
-H "app_key: APP_KEY" \
-H "Content-Type: application/json" \
--data '{
"urls": {
"inverted": {
"url": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/inverted.jpg",
"ocr_behavior": "text",
"formats": ["text", "html", "data"],
"data_options": {"include_asciimath": true}
},
"algebra": {
"url": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/algebra.jpg",
"ocr_behavior": "text",
"formats": ["text", "html", "data"],
"data_options": {"include_asciimath": true}
}
}
}'
import requests
base_url = "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/"
r = requests.post("https://api.mathpix.com/v3/batch",
json={
"urls": {
"inverted": {
"url": base_url + "inverted.jpg",
"ocr_behavior": "text",
"formats": ["text", "html", "data"],
"data_options": {"include_asciimath": True}
},
"algebra": {
"url": base_url + "algebra.jpg",
"ocr_behavior": "text",
"formats": ["text", "html", "data"],
"data_options": {"include_asciimath": True}
}
}
},
headers={
"app_id": "APP_ID",
"app_key": "APP_KEY",
"content-type": "application/json"
}
)
print(r.json())
const base = "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/";
const response = await fetch("https://api.mathpix.com/v3/batch", {
method: "POST",
headers: {
app_id: "APP_ID",
app_key: "APP_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
urls: {
inverted: {
url: base + "inverted.jpg",
ocr_behavior: "text",
formats: ["text", "html", "data"],
data_options: { include_asciimath: true },
},
algebra: {
url: base + "algebra.jpg",
ocr_behavior: "text",
formats: ["text", "html", "data"],
data_options: { include_asciimath: true },
},
},
}),
});
const { batch_id } = await response.json();
console.log(`Batch ID: ${batch_id}`);
body := bytes.NewBufferString(`{
"urls": {
"inverted": {
"url": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/inverted.jpg",
"ocr_behavior": "text",
"formats": ["text", "html", "data"],
"data_options": {"include_asciimath": true}
},
"algebra": {
"url": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/algebra.jpg",
"ocr_behavior": "text",
"formats": ["text", "html", "data"],
"data_options": {"include_asciimath": true}
}
}
}`)
req, _ := http.NewRequest("POST", "https://api.mathpix.com/v3/batch", body)
req.Header.Set("app_id", "APP_ID")
req.Header.Set("app_key", "APP_KEY")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
result, _ := io.ReadAll(resp.Body)
fmt.Println(string(result))
HttpClient client = HttpClient.newHttpClient();
String body = """
{
"urls": {
"inverted": {
"url": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/inverted.jpg",
"ocr_behavior": "text",
"formats": ["text", "html", "data"],
"data_options": { "include_asciimath": true }
},
"algebra": {
"url": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/algebra.jpg",
"ocr_behavior": "text",
"formats": ["text", "html", "data"],
"data_options": { "include_asciimath": true }
}
}
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.mathpix.com/v3/batch"))
.header("app_id", "APP_ID")
.header("app_key", "APP_KEY")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
Both request formats return the same response:
{
"batch_id": 18
}
Use callbacks
Receive results automatically when the batch completes by including a callback object in the v3/batch request:
- Request body
- cURL
- Python
- JavaScript / TypeScript
- Go
- Java
{
"urls": {
"inverted": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/inverted.jpg"
},
"formats": ["latex_simplified"],
"callback": {
"post": "https://your-server.com/webhook",
"headers": { "Authorization": "Bearer YOUR_TOKEN" }
}
}
curl -X POST https://api.mathpix.com/v3/batch \
-H "app_id: APP_ID" \
-H "app_key: APP_KEY" \
-H "Content-Type: application/json" \
--data '{
"urls": {
"inverted": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/inverted.jpg"
},
"formats": ["latex_simplified"],
"callback": {
"post": "https://your-server.com/webhook",
"headers": {"Authorization": "Bearer YOUR_TOKEN"}
}
}'
import requests
r = requests.post("https://api.mathpix.com/v3/batch",
json={
"urls": {
"inverted": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/inverted.jpg"
},
"formats": ["latex_simplified"],
"callback": {
"post": "https://your-server.com/webhook",
"headers": {"Authorization": "Bearer YOUR_TOKEN"}
}
},
headers={
"app_id": "APP_ID",
"app_key": "APP_KEY",
"content-type": "application/json"
}
)
print(r.json())
const response = await fetch("https://api.mathpix.com/v3/batch", {
method: "POST",
headers: {
app_id: "APP_ID",
app_key: "APP_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
urls: {
inverted: "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/inverted.jpg",
},
formats: ["latex_simplified"],
callback: {
post: "https://your-server.com/webhook",
headers: { Authorization: "Bearer YOUR_TOKEN" },
},
}),
});
const { batch_id } = await response.json();
console.log(`Batch ID: ${batch_id}`);
body := bytes.NewBufferString(`{
"urls": {
"inverted": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/inverted.jpg"
},
"formats": ["latex_simplified"],
"callback": {
"post": "https://your-server.com/webhook",
"headers": {"Authorization": "Bearer YOUR_TOKEN"}
}
}`)
req, _ := http.NewRequest("POST", "https://api.mathpix.com/v3/batch", body)
req.Header.Set("app_id", "APP_ID")
req.Header.Set("app_key", "APP_KEY")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
result, _ := io.ReadAll(resp.Body)
fmt.Println(string(result))
HttpClient client = HttpClient.newHttpClient();
String body = """
{
"urls": {
"inverted": "https://raw.githubusercontent.com/Mathpix/api-examples/master/images/inverted.jpg"
},
"formats": ["latex_simplified"],
"callback": {
"post": "https://your-server.com/webhook",
"headers": { "Authorization": "Bearer YOUR_TOKEN" }
}
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.mathpix.com/v3/batch"))
.header("app_id", "APP_ID")
.header("app_key", "APP_KEY")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
{
"batch_id": 18
}
Even with a callback, there is no guarantee it will succeed (e.g., due to transient network failure). Always poll as a fallback.
Next steps
- v3/batch reference - Full request parameters, response schema, and callback object
- Process an Image - For single image processing