ForHosting KIT · OCR & Data Extraction

Digitize a menu

A laminated menu photographed at a table is the last format anyone wants to build a delivery app or price comparison tool on top of, yet it's often the only format that exists. This endpoint reads that photo and returns each dish, its description and its price as structured entries, ready to populate a menu database instead of a spreadsheet someone typed by hand overnight.

● BetaPer request + per image$0.010
Use it from WebAPIEmailApp soonTelegram soon

Run this on our servers with your account. Free tools run in your browser; this one bills your KIT balance per the price above.

The dataset that never got digitized

Most restaurant menus exist only as a printed card, a laminated sheet or a chalkboard photo, updated by hand whenever a price or dish changes and never entered into any system beyond the point-of-sale terminal, if that. Any platform that wants to list a restaurant's actual dishes and prices, rather than a stale PDF from two years ago, runs into the same task: turning a photograph of a menu into rows of data.

What the endpoint pulls out

It reads the dish name, its description when the menu includes one, and its price, grouping items under the section headers a menu typically uses, such as starters, mains or desserts. Multi-column layouts, mixed fonts for section titles versus items, and prices placed either beside or below a dish name are all part of what real menus look like, and the extraction is built around that variability rather than a single clean template.

Handling the messiness of real menus

Menus are one of the least standardized documents in daily use: some list prices with currency symbols, others assume the diner knows the currency, some print a single price and others list small and large sizes side by side. The endpoint captures what is printed as printed, so a menu with size-based pricing returns both prices tied to the same dish rather than picking one and discarding the other.

The request in practice

Send the photo to POST /ocr/menu and get a task_id back immediately, since digitization runs asynchronously behind the scenes. The structured menu arrives through your signed webhook or a signed link valid for 24 hours, and a photo too blurry or dark to parse after three internal retries returns a clear error with no charge.

Where it plugs into a bigger system

Delivery platforms use it to onboard a restaurant's current offering without a staff member manually typing every line, price comparison tools refresh listings whenever an owner sends an updated photo, and franchise operators standardize menu data across dozens of locations that each print their own physical card.

Onboarding a restaurant to a delivery platform

A new restaurant partner sends a photo of their printed menu and the platform populates dishes, descriptions and prices without staff retyping the card.

Keeping listings current after a price change

An owner photographs the updated menu after a price revision, and a comparison site refreshes its listing instead of showing outdated prices for months.

Standardizing data across franchise locations

A franchise operator digitizes the slightly different printed menus from each branch into one consistent product catalog.

Building a searchable menu archive

A food blog converts photographed menus from reviewed restaurants into searchable dish listings readers can browse by cuisine or price.

What does a menu digitization API do?

It reads a photo of a restaurant menu and returns each dish's name, description and price as structured data, grouped by menu section.

Is there a free tier?

There's no free tier — free tiers get abused and slow everyone down. Access runs on a prepaid ForHosting KIT balance: top up from $10.00 (it never expires) and each request is charged at its published price, so a call with no balance returns HTTP 402. No subscription, no tokens, no invented credits, and a failed task is never charged.

How much does it cost per menu photo?

$0.010 per request plus $0.0575 per image, and you're only charged for tasks that complete successfully.

Does it handle menus with multiple prices per dish?

Yes, when a menu lists more than one price for a dish, such as small and large sizes, both are captured and tied to that same dish rather than collapsed into one.

What if the menu has multiple columns or sections?

Multi-column layouts and section headers like starters, mains or desserts are part of normal menu design, and the extraction groups items under their correct section.

How do I get the digitized menu back?

Call POST /ocr/menu to receive a task_id immediately, then get the structured menu via a signed webhook or a signed link valid for 24 hours.

What happens with a blurry or handwritten chalkboard menu?

The system retries internally up to three times; if the photo still can't be reliably parsed, you receive a clear error and no charge.

Can I digitize many restaurant menus in bulk?

Yes, each menu photo is processed as its own asynchronous task, so you can submit a batch and collect each result as it finishes.

Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.

POSThttps://api.kit.forhosting.com/ocr/menu

Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, and soon from our app, email and Telegram.

curl -X POST https://api.kit.forhosting.com/ocr/menu \
  -H "Authorization: Bearer $KIT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"image":"https://ejemplo.com/imagen.jpg"}'
{
  "image": "https://ejemplo.com/imagen.jpg"
}
{
  "task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
  "type": "ocr.menu",
  "status": "queued",
  "_links": {
    "result": "/tasks/tsk_…/result"
  }
}

The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.

Per request$0.010
Per image$0.0575

Published price — no tokens, no invented credits. A failed task is never charged.

max_mb25
max_pages10
HTTPCodeMeaning
401unauthorizedMissing or invalid API key.
402insufficient_balanceYour balance doesn't cover the task price.
404unknown_typeThat task type doesn't exist.
429rate_limitedToo many requests. Use the webhook instead of polling.
422task_failedThe task failed after 3 retries. You are never charged for it.

Read the full KIT documentation →