Web and domain tooling

Image OCR Text Extractor: text from image URLs, per line

Text extraction (OCR) from images by URL, up to 200 per run: every line with its confidence and position, the full text joined, image size and format, for screenshots, scans, receipts, menus and product labels, without a browser or an API key. Pay per image with text.

$2.00per 1,000 · Image read

One image delivered with its text. Images without readable text, unreachable files and non-images are never charged.

Call it from your code

curl
ACTOR=steadydata~image-ocr-text
URL="https://api.apify.com/v2/acts/$ACTOR/run-sync-get-dataset-items"

curl -X POST "$URL?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"urls": ["https://raw.githubusercontent.com/madmaze/pytesseract/master/tests/data/test.png"], "minConfidence": "0.5"}'
python
import os, requests

ACTOR = "steadydata~image-ocr-text"
URL = f"https://api.apify.com/v2/acts/{ACTOR}/run-sync-get-dataset-items"

rows = requests.post(
    URL,
    params={"token": os.environ["APIFY_TOKEN"]},
    json={'urls': ['https://raw.githubusercontent.com/madmaze/pytesseract/master/tests/data/test.png'], 'minConfidence': '0.5'},
    timeout=900,
).json()

# every row carries a status; failures are records, not exceptions
ok = [r for r in rows if r.get("status") == "ok"]
print(len(ok), "rows delivered")
javascript
const ACTOR = "steadydata~image-ocr-text";
const url =
  `https://api.apify.com/v2/acts/${ACTOR}/run-sync-get-dataset-items` +
  `?token=${process.env.APIFY_TOKEN}`;

const rows = await fetch(url, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({"urls": ["https://raw.githubusercontent.com/madmaze/pytesseract/master/tests/data/test.png"], "minConfidence": "0.5"}),
}).then((r) => r.json());

// one object per delivered row, same shape every time
console.log(rows.filter((r) => r.status === "ok").length, "rows");

Use it in an agent

Point an MCP client at Apify's hosted server with this dataset in the tools list, or run our own server locally. The field explanations in the table below travel with the schema, so your agent reads them straight from the platform instead of from this page.

mcp url
https://mcp.apify.com?tools=steadydata/image-ocr-text

# the tool arrives in your agent as steadydata--image-ocr-text

Input

FieldTypeNameWhat it does
urls
required
array of stringImage URLsOne URL per row, up to 200: PNG, JPEG, WebP, GIF, BMP or TIFF.
minConfidencestringMinimum confidence per lineLines below this OCR confidence (0 to 1) are dropped; 0.5 keeps almost everything, 0.8 only clean text.

What you get back

output schema, one object per delivered row
{
  "url": string | null,
  "text": string | null,
  "lines": array | null,
  "lineCount": integer | null,
  "avgConfidence": number | null,
  "boxes": array | null,
  "width": integer | null,
  "height": integer | null,
  "format": string | null,
  "fileBytes": integer | null,
  "processedMs": integer | null,
  "status": string | null,
  "input": string | null,
  "errorCode": string | null,
  "error": string | null
}
FieldTypeWhen it is filled
urlstring, null
textstring, null
linesarray, null
lineCountinteger, null
avgConfidencenumber, null
boxesarray, null
widthinteger, null
heightinteger, null
formatstring, null
fileBytesinteger, null
processedMsinteger, null
statusstring, nullEither 'ok' or 'error'. An error row carries errorCode and error, and leaves the data fields empty; it is never charged.
inputstring, nullThe input this row was built from, so a row can always be traced back.
errorCodestring, nullFilled on an error row only; a delivered row leaves it empty.
errorstring, nullFilled on an error row only; a delivered row leaves it empty.

Related datasets

Already using this one? Ratings are the first thing other buyers look at, and this dataset has none yet. If it does a job for you, a rating on its Apify page is the one thing that helps. It takes a minute and it is the only thing we ask for.

Open the Apify page