Image to Excel

API Documentation

Send a picture of a table, get the rows back as JSON or as an Excel file.

Overview

The API runs the same table extraction as the website. You post one image per request and it answers with the detected table, either as rows of text in JSON or as a ready-made .xlsx file. Every request is plain HTTPS and every reply, apart from the spreadsheet download, is JSON.

Base URL: https://imagetoexcel.net/api/v1

API plans are sold separately from the web plans and have their own credit balance. Create and manage keys in your profile.

Authentication

Send your key with every request, either as a bearer token or in an X-API-KEY header:

Authorization: Bearer YOUR_API_KEY
# or
X-API-KEY: YOUR_API_KEY

Each account has two kinds of key:

  • Sandbox key (starts with sk_test_). Free, available from signup, and it never reads your image. It always returns the same sample table, so you can build and test your integration without spending credits.
  • Live key (starts with sk_live_). Reads your image and uses credits. It needs an active API plan.

Keep keys on your server. If one leaks, revoke it from your profile and create a new one.

Convert an image

POST https://imagetoexcel.net/api/v1/image-to-excel

Parameters

Send a multipart/form-data body. Provide the image in exactly one of the first three ways.

FieldTypeDescription
imagefileThe image, uploaded as a file.
base64stringThe image as base64. A full data: URI or the bare base64 string both work.
image_urlstringA public URL we download the image from. The host must answer within 15 seconds.
output_typestringjson (default) returns the rows. file returns an .xlsx download.
filenamestringOptional name for the downloaded file, up to 120 characters. Only used with output_type=file.

Accepted image types: JPEG, PNG, WebP, BMP, GIF, TIFF, HEIC and HEIF. PDFs are not accepted by the API. The type is detected from the file contents, not from its name.

Examples

cURL

curl -X POST "https://imagetoexcel.net/api/v1/image-to-excel" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "image=@invoice.jpg"

Download as Excel

curl -X POST "https://imagetoexcel.net/api/v1/image-to-excel" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "image_url=https://example.com/report.png" \
  -F "output_type=file" \
  -o report.xlsx

JavaScript

const form = new FormData();
form.append("image", fileInput.files[0]);

const res = await fetch("https://imagetoexcel.net/api/v1/image-to-excel", {
  method: "POST",
  headers: { Authorization: "Bearer YOUR_API_KEY" },
  body: form,
});
const data = await res.json();
console.log(data.rows);

Python

import requests

res = requests.post(
    "https://imagetoexcel.net/api/v1/image-to-excel",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    files={"image": open("invoice.jpg", "rb")},
)
print(res.json()["rows"])

Response

With output_type=json, rows is a list of rows and each row is a list of cell values in column order:

{
  "error": false,
  "sandbox": false,
  "rows": [
    ["Date", "Description", "Debit", "Credit"],
    ["2026-01-09", "ACME Supplies Ltd", "312.40", ""]
  ],
  "meta": { "row_count": 2, "column_count": 4 }
}

Cell values are returned as text exactly as read from the image. We do not convert or round numbers, so parse them on your side. With output_type=file the response body is the spreadsheet itself, sent as an attachment.

A successful live request uses 1 credit. If no table can be read from the image you get a no_table_found error and no credit is used.

Account and balance

GET https://imagetoexcel.net/api/v1/account

Returns your plan limits and remaining credits, so an integration can show usage or slow down before it runs out.

curl "https://imagetoexcel.net/api/v1/account" \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "error": false,
  "plan": {
    "name": "Plus",
    "tier": "plus",
    "max_file_mb": 20,
    "requests_per_minute": 30
  },
  "credits": {
    "remaining": 940,
    "allowance": 1000,
    "renews_at": "2026-11-01T00:00:00+00:00"
  }
}

Errors

Failed requests return a non-2xx status and a JSON body with a stable code to branch on and a readable message:

{
  "error": true,
  "code": "invalid_api_key",
  "message": "Invalid API key."
}
StatusCodeMeaning
401 missing_api_key No key was sent.
401 invalid_api_key The key does not exist or has been revoked.
402 insufficient_credits Your credits for this month are used up.
403 no_active_plan This live key has no active API plan. Use the sandbox key or subscribe.
422 missing_image None of image, base64 or image_url was sent.
422 invalid_input The upload, base64 value or image_url could not be read or downloaded.
422 file_too_large The image is bigger than your plan allows.
422 unsupported_type The file is not one of the accepted image types.
422 no_table_found No table could be read from the image. No credit is used.
429 rate_limited Too many requests this minute for your plan.

A malformed output_type, image_url or filename is rejected with status 422 and a message plus an errors object naming the field.

Limits and credits

One image costs 1 credit. Credits renew in full every month and unused ones do not roll over. File size and request rate depend on your API plan:

PlanMax image sizeRequests per minute
Lite 10 MB 15
Plus 20 MB 30
Pro 30 MB 50

Limits are counted per key, so two keys on one account each get their own request budget. When you receive a 429, wait a minute and retry. Current monthly prices are on the pricing section (pick the API tab); for more than the largest plan, contact us.