AI Data Extraction
Pricing
from $10.00 / 1,000 document processeds
AI Data Extraction
Extract custom data from PDF, DOCX, and images using AI. Turn invoices, forms, and other documents into structured, validated JSON. Simply provide document URLs and define the fields you need.
Pricing
from $10.00 / 1,000 document processeds
Rating
0.0
(0)
Developer
Amine Ch
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
8 days ago
Last modified
Categories
Security
Limited permissionsShare
Universal AI Document Extractor
Turn PDFs, Word documents and images into structured JSON. You decide which fields you want.
Give the Actor a list of document URLs and a list of fields (name, description, type). It downloads each document, reads it (native text, tables, OCR for scans, or visually), asks an AI model for exactly those fields, validates the answer, and returns one clean result per document. It is a document extraction engine, not an autonomous agent: it does one job and never browses, scrapes or acts on your behalf.
It works for any document type because you define the fields: invoices, receipts, contracts, CVs/resumes, purchase orders, financial statements, application forms, registration documents and other business documents.
What you get
- Your fields, your types.
string,number,integer,boolean,date(ISO 8601),array,object. - Honest nulls. A field that is not in the document is
nullwith statusnot_found. It is never guessed. An illegible one isunreadable. - Confidence estimates per field (optional).
- Source references per field: page number and the supporting text (optional). Each reference says whether the quoted text was actually found in the document (
text_verified), and page numbers are never invented. - Per-document results. One failing document never stops the others.
- Predictable cost. Native text first, OCR only for scans, hard limits on size, pages and tokens, and exact token usage in every result.
Supported documents
| Type | Extensions | How it is read |
|---|---|---|
.pdf | Native text and tables (Markdown). Pages without usable text are OCR'd and sent to the AI as an image plus OCR text. Form-field values are included. | |
| Word | .docx | Headings, paragraphs, tables (including merged cells), headers/footers, tracked insertions, text boxes. |
| Images | .jpg .jpeg .png .webp | EXIF orientation applied, transparency flattened, OCR plus the image itself. |
Not supported: legacy .doc, password-protected files, spreadsheets, presentations, web pages, and direct file uploads (documents must be reachable by public HTTPS URL).
Quick start
Input
{"documents": [{ "url": "https://example.com/invoice.pdf", "filename": "invoice.pdf" }],"fields": [{ "name": "invoice_number", "description": "The unique invoice identifier", "type": "string" },{ "name": "invoice_date", "description": "The invoice issue date", "type": "date" },{ "name": "supplier_name", "description": "The legal name of the supplier", "type": "string" },{ "name": "total_amount", "description": "The final amount including taxes", "type": "number" }]}
Output (one dataset item per document)
{"index": 0,"success": true,"url": "https://example.com/invoice.pdf","document": { "filename": "invoice.pdf", "type": "pdf", "pages": 1 },"extracted_data": {"invoice_number": "INV-2026-0417","invoice_date": "2026-10-20","supplier_name": "Northwind Synthetic Trading Ltd","total_amount": 1011.5},"field_status": {"invoice_number": "found", "invoice_date": "found", "supplier_name": "found", "total_amount": "found"},"confidence": {"invoice_number": 0.98, "invoice_date": 0.97, "supplier_name": 0.9, "total_amount": 0.97},"sources": {"invoice_number": { "page": 1, "text": "Invoice No: INV-2026-0417", "location": null, "text_verified": true },"total_amount": { "page": 1, "text": "Total Due: 1,011.50 EUR", "location": null, "text_verified": true }},"charges": { "document-processed": 1 },"usage": {"pages_processed": 1, "ocr_pages": 0, "vision_pages": 0,"ai_requests": 1, "ai_input_tokens": 1828, "ai_output_tokens": 793}}
A failed document looks like this (the other documents are unaffected):
{"index": 3,"success": false,"url": "https://example.com/missing.pdf","document": { "filename": "missing.pdf", "type": null, "pages": null },"usage": { "pages_processed": 0, "ocr_pages": 0, "vision_pages": 0, "ai_requests": 0, "ai_input_tokens": 0, "ai_output_tokens": 0 },"error": { "code": "DOWNLOAD_FAILED", "message": "The document was not found at the given URL." }}
The run also saves a SUMMARY record in the key-value store: documents succeeded and failed, failures by error code, pages, AI token totals and billing totals (events charged, documents skipped by a limit). It contains counts only, never document contents.
Input reference
| Field | Type | Default | Description |
|---|---|---|---|
documents | array, required | – | 1–100 items: { "url": "https://…", "filename": "optional" }. HTTPS only. |
fields | array, required | – | 1–100 items: { "name", "description", "type" }. |
language | string | auto | auto or a code like en, fr, de. Improves OCR for scans. |
include_confidence | boolean | true | Per-field confidence estimate. |
include_source_references | boolean | true | Per-field page and supporting text. |
vision_mode | auto | never | always | auto | See How reading works. |
max_file_size_mb | integer 1–50 | 20 | Larger files are rejected. |
max_pages | integer 1–100 | 30 | PDFs with more pages are rejected (not truncated). |
max_output_tokens | integer 256–16000 | automatic | Leave empty to size it from the number of fields (about 120 tokens per field). |
output_format | json | json | Only JSON is supported. |
Field definitions. name must start with a letter or underscore and contain only letters, digits and underscores (max 64, unique ignoring case). description (max 500 characters, optional but strongly recommended) tells the AI what you mean, and it is the single biggest lever on accuracy. type defaults to string. For array and object fields, describe the structure in the description:
{ "name": "line_items", "type": "array","description": "Array of objects with description, quantity, unit_price and amount for each invoice line" }
Type rules: numbers have currency symbols and thousands separators removed ("1.234,50 €" → 1234.5); dates are normalised to YYYY-MM-DD (or YYYY-MM / YYYY when the document gives less). If a date cannot be normalised it is returned as written and a warning is added; the AI never assumes a currency that the document does not state.
Pricing and limits
This Actor uses Apify's pay-per-event pricing. The Pricing section of the Actor page always shows the current prices; at launch they are:
| Event | Charged | Launch price |
|---|---|---|
document-processed | once for every document that was successfully extracted (first page included) | $0.01 |
extra-page | for every PDF page after the first | $0.002 |
vision-page | for every page the AI read as an image (scans and photos) | $0.005 |
- You pay only for results. Failed documents (download errors, unsupported or corrupted files, blocked URLs, AI failures, documents skipped by a limit) are never charged. Platform usage is included in the price.
- Every result shows what it cost, in
charges. A Word document counts as one document with no extra pages. - Examples: a 1-page invoice PDF costs $0.01; a 14-page text PDF costs $0.01 + 13 x $0.002 = $0.036; a 3-page scan read as images costs $0.01 + 2 x $0.002 + 3 x $0.005 = $0.029; a photo costs $0.01 + $0.005 = $0.015.
- Spending limit. Set maximum charge per run in the run options. A document is only started if its full price still fits; otherwise it is skipped, not charged, and reported as
SPENDING_LIMIT_REACHED. The run still finishes normally. - Free Apify plan. To keep the Actor sustainable, runs on the free plan are limited to 3 documents and 10 pages per run (processed in the order you list them). Anything beyond is skipped with
FREE_PLAN_LIMITand a clear status message. Paid plans have no such limit.
How reading works
- Download the document from its public HTTPS URL.
- Detect the real file type from the file's content (not just its name).
- Extract content:
- PDF: native text in reading order, tables as Markdown. Pages with little or no text, or garbled font encoding, are treated as scans.
- Scans and images: Tesseract OCR (English, French, German, Spanish, Italian, Portuguese, Dutch) and, in
automode, the page image itself. We measured that OCR alone can silently drop table headers and whole columns even when its confidence score is high, so scanned pages go to the AI as image + OCR text. Up to 10 pages per document are sent as images; further scanned pages use OCR text only and the result carries a warning saying so. - DOCX: structure-preserving text.
- Ask the AI for the requested fields only. The document is treated strictly as data.
- Validate the reply against your field types. If the reply is malformed it is retried once with the validation errors (never with extracted values). Values are nulled unless the field is
found. - Check the sources. Quotes are matched against the extracted text; a wrong page is corrected, a quote that cannot be found is flagged
text_verified: false.
vision_mode: auto (recommended) sends scanned pages as image + OCR; never uses text and OCR only (cheapest, but may miss table content in scans); always also sends every text page as an image (highest accuracy and cost).
Confidence values are the model's own estimates, not calibrated probabilities, and are null unless a field was found. text_verified: false does not mean a value is wrong: image-only pages have no text to match against, and OCR can differ slightly from the quote.
Error codes
Run-level problems (invalid input, a model that is not available) stop the run immediately with a clear status message before anything is processed or billed. Per-document errors appear in that document's error field:
| Code | Meaning |
|---|---|
UNSAFE_URL | The URL is not allowed. Use a public https:// link. |
DOWNLOAD_FAILED | Not found, requires authentication, server error, timed out, empty. |
FILE_TOO_LARGE | Over max_file_size_mb (or an image with an extreme pixel count). |
UNSUPPORTED_FILE_TYPE | Not PDF/DOCX/JPG/PNG/WEBP, or the extension contradicts the content. |
CORRUPTED_DOCUMENT | The file cannot be parsed. |
ENCRYPTED_DOCUMENT | Password-protected PDF. |
PAGE_LIMIT_EXCEEDED | More pages than max_pages. |
NO_READABLE_CONTENT | No text and nothing the OCR/AI could read (e.g. a DOCX that only contains pictures). |
DOCUMENT_TOO_LARGE | Too much text for one AI request (about 400,000 characters). |
AI_OUTPUT_TRUNCATED | The reply hit max_output_tokens. Raise it or request fewer fields. |
AI_INVALID_RESPONSE | The AI reply was still invalid after one correction request. |
AI_REFUSED | The AI declined to process the document. |
AI_RATE_LIMITED / AI_TIMEOUT / AI_UNAVAILABLE / AI_REQUEST_REJECTED / AI_PROVIDER_ERROR | Provider-side problems. |
FREE_PLAN_LIMIT | Free Apify plan: more than 3 documents or 10 pages in one run. The document was not processed. See Pricing and limits. |
SPENDING_LIMIT_REACHED | The maximum charge you set for the run was reached; the document was not processed and not charged. |
INTERNAL_ERROR | Unexpected error; no internal detail is exposed. |
Run it from the API
Start it from the Apify Console (Input tab) or call it through the API:
cURL (synchronous run, returns the dataset items):
curl -X POST "https://api.apify.com/v2/acts/U9GpBbmIMUe5XH5sg/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"documents": [{ "url": "https://example.com/invoice.pdf" }],"fields": [{ "name": "invoice_number", "description": "The unique invoice identifier", "type": "string" },{ "name": "total_amount", "description": "The final amount including taxes", "type": "number" }]}'
Python (pip install apify-client):
from apify_client import ApifyClientclient = ApifyClient("<APIFY_TOKEN>")run = client.actor("U9GpBbmIMUe5XH5sg").call(run_input={"documents": [{"url": "https://example.com/invoice.pdf"}],"fields": [{"name": "invoice_number", "description": "The unique invoice identifier", "type": "string"},{"name": "total_amount", "description": "The final amount including taxes", "type": "number"},],})for item in client.dataset(run["defaultDatasetId"]).iterate_items():if item["success"]:print(item["extracted_data"])else:print("failed:", item["error"]["code"], item["error"]["message"])
For many documents, start the run asynchronously (.start() / POST /acts/{id}/runs) and read the dataset when it finishes.
Limitations
- Documents must be public HTTPS URLs (no authentication, no direct upload yet).
- DOCX: images, footnotes/endnotes and comments are not read. A DOCX containing only pictures is rejected with
NO_READABLE_CONTENT; send the images themselves. - OCR uses English, French, German, Spanish, Italian, Portuguese and Dutch data. Other scripts rely on the AI reading the page image (
vision_mode: autofalls back to this when OCR is unreliable). - Handwriting and very low-quality scans depend on what the model can read; check
confidenceandwarnings. - Tables are given to the AI as Markdown, whose first row looks like a header; mention the table structure in a field description if it matters ("first row below the column headings").
- Very large documents are rejected (not chunked) once they exceed the page, size or input-character limits; the model's context is large enough that splitting would add cost and lose cross-page context.
- Not a substitute for human review where errors are costly.
Your data
Documents are processed only for the duration of the run and are not stored by the Actor. Their content is sent to a third-party AI service to extract the fields you ask for, so make sure you have the right to process the documents, especially if they contain personal data.