PDF Text Extractor with Page Level Output
Pricing
Pay per event
PDF Text Extractor with Page Level Output
Extract text from authorized digital PDF documents into one JSON record per document, with page numbers, SHA256, metadata and clear scan or limit notices.
Pricing
Pay per event
Rating
0.0
(0)
Developer
Tim Zinin
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Extract text from authorized digital PDF documents into one JSON record per complete document, with page numbers, SHA256, metadata and clear scan or limit notices.
Evidence status (2026-09-05). The actor was built on the Apify platform (build aX54FgGiPGrTo9gAv), its pay-per-event tariff was read back from the platform, and four private acceptance runs on Apify infrastructure produced the rows shown in this document: a digital-text PDF, a blank PDF, an image-only scan and a 26-page document above the page limit.
R1. What you get
Get digital PDF text grouped by physical page, a document hash, bounded metadata and an explicit outcome for scans and unsupported files. The paid result is one complete document, with each extracted page carrying pageNumber, text and charCount. This is useful when an importer needs page provenance and a clear distinction between real text extraction and a document that needs OCR.
The extractor is built for PDF text layers. It does not perform OCR, reconstruct visual layouts, interpret charts, export embedded attachments, execute document JavaScript or make a legal or semantic judgment about the text. A scanned image can look readable in a viewer while containing no text layer at all. Such a file is routed to requires_ocr without a document result charge.
A digital PDF is accepted only when every page fits the requested maximum and the complete extraction fits the text and output bounds. The actor does not sell the first25 pages of a26-page document as though it completed the file. The document unit stays intact: the whole file succeeds, produces a clean negative or explains why it could not be completed.
R2. Who uses it
Search and knowledge-base developers can ingest text while retaining page references for later retrieval. Document operations teams can classify a small authorized batch into importable digital documents, blank files, scans needing OCR and files that require preparation. Analysts can collect text from their own generated reports without deploying a browser or an OCR service for documents that already contain a usable text layer.
An archive workflow can use SHA256 as the immutable source-byte key and preserve pageNumber in child text records. A reporting workflow can keep one parent record per PDF and compare the extracted page text across approved report revisions. Both need to handle errors as failed attempts rather than replacing the previous report with an empty value.
This product is a poor fit for handwritten scans, visual table reconstruction, page-coordinate annotation, interactive form submission, password recovery or unbounded books. If your process needs text from pictures, use an authorized OCR stage after requires_ocr. If it needs page geometry or reading-order reasoning, review a tool that explicitly supports those outputs; the plain text contract here does not imply them.
R3. How to run
Choose Try, inspect the input form, keep the small fixture prefill for your first check, and select Start. After the run, open Dataset for records and the default key-value store's OUTPUT record for the summary. Download JSON if you need to preserve nested arrays, numeric values, booleans and nulls. A spreadsheet export can hide those distinctions, so use CSV as a presentation format rather than the authoritative conversion archive.
Replace the fixture URLs with direct public HTTP or HTTPS download URLs for files you own or are authorized to process. A document viewer URL, cloud-drive preview or login page is not necessarily a download. Test your final URL without your browser's authenticated session. This actor sends no browser cookies and accepts no username/password URL. If a file service requires a signed query string, keep the run and output private: source URLs are included in provenance and may expose that temporary access link to anyone who can read the dataset.
Keep input and result limits small until a representative file succeeds. Then save the exact input as a task. A task stores configuration; it does not change the actor's hard safety bounds. For recurring work, connect that task to Apify's existing scheduling feature and choose a frequency that matches your document publication cycle. The actor does not create schedules, messages, tickets or workflows on your behalf.
Inspect both useful records and free notices before adding automation. A successful process status is not a count of useful documents. Conversely, a run that later fails can retain useful records already delivered. Save the run ID, build version, input, dataset ID and OUTPUT summary together so a colleague can reconcile the actual observation without inferring it from a screenshot or a file name.
For the default, leave fileUrls set to the hosted pdf-text.pdf fixture, maxPages at25 and maxTextChars at200000. The original file contains two pages with the exact phrases WAVE-A PAGE ONE MARKER and WAVE-A PAGE TWO MARKER. The local proof below verifies both markers; hosted prefill availability is verified by Claude after uploading the binary.
For your first real file, choose a small PDF with selectable text and no password. Set maxPages to at least its total page count, retain a modest budget and check that the returned page numbers cover the expected document. Test a representative scan separately so the receiving workflow has an approved requires_ocr path instead of treating it as a silent empty import.
R4. Pricing
The price is $0.003 per start + $0.002 per document, read back from the platform tariff on 2026-09-05 (apify-actor-start $0.003, result-found $0.002, model PAY_PER_EVENT). A run with one useful PDF is $0.005; five useful PDFs in one run are $0.013. One hundred useful PDFs split into20 runs of five are $0.26 at that tariff. Blank, image-only scan, password, corrupt-file and limit notices have no result event. Those arithmetic examples are not receipts.
The primary paid unit is one complete digital-text PDF document, with its pages nested in a single record. A complete useful record is delivered with one named result-found event in the same Actor.pushData call. There is no separate request to charge a result and no page/cell/text-fragment surcharge hidden inside the record. A free notice has found:false and resultCount:0, and is written without a result event. You can therefore see more dataset rows than paid results.
Platform evidence for the tariff above (charged event counts of the accepted runs): digital-text PDF GtMD6KgHhXMut5HHG result-found: 1; blank PDF jChC23r2jngkUujT7 0; image-only scan 8gyQq16LSKNgaKA9z 0; 26-page document above the limit 2K9lyWwhyslzhEJa2 0. The start event is charged once per GB of run memory: the default 256 MB run pays one start unit, while the acceptance runs were started with 4096 MB and therefore show apify-actor-start: 4. Keep the default memory unless a large document needs more; a different memory setting changes the start charge shown by the platform, not the meaning of a result event.
At runtime the actor reads actual pricing from the initialized Apify SDK. A platform run with unreadable pricing, no positive result-found price, invalid event prices, or a priced automatic dataset-item event fails closed. The actor will not use an explanatory dataset write if that write could itself be billable. In that situation the explanation is in the run log and failed status. A start event may already exist, so a failure is not a promise of a zero invoice.
The remaining budget is checked immediately before a paid write, inside the same lock as the write. This matters at the boundary: a cap one microdollar below the next complete unit must not be rounded up to buy that unit. Concurrent calls share the lock, and the last paid record still counts if the SDK returns an event-limit flag with its successful write. Subsequent paid work stops; previously delivered records remain available.
If storage or charging fails during a paid write, the result can be uncertain. A row may have reached storage before the charge acknowledgement failed. The actor stops, records deliveryUncertain and fails the run; it does not retry the same row automatically. Inspect the dataset and charged event counters before rerunning that input. There is no persistent replay ledger, so a new successful run can deliver and bill the same file contents again.
Set a run budget independently of input caps. An input cap bounds document processing; a monetary cap bounds additional result events. Neither is a quota for the other. A tiny budget can prevent delivery even when the parser produced useful content, while a large budget does not permit files beyond byte, page, cell, pixel or runtime bounds. Use requested/processed/unprocessed and delivered/paid/free together when explaining that difference to your team.
R5. Input contract
| Field | Prefill | Contract |
|---|---|---|
| fileUrls | ["https://api.apify.com/v2/key-value-stores/b0cgFsJRqVv3XOZyG/records/pdf-text.pdf"] | One to five public HTTP(S) URLs of PDF files you own or are authorized to process. No credentials, fragments or private-network addresses. The prefill is our synthetic two-page fixture. |
| maxPages | 25 | Reject a whole document if its total page count exceeds this limit. No truncated document is charged. Up to125 pages across five files. |
| maxTextChars | 200000 | Total extraction character budget per document, including extraction separators. Exceeding it produces a free partial limit notice, not truncated billable text. |
Every field is validated before expensive work. Unknown properties, wrong types and oversized arrays are rejected; numeric strings are not silently coerced to integers. Arrays of source URLs are checked before any multiplicative resource limit. URLs must be absolute, at most2048 characters, HTTP or HTTPS, with no credentials or fragment. Duplicate identical normalized URLs in the same input are processed once; query parameters are retained because they can select a different file or grant access to a particular version.
Private, loopback, link-local and cloud-metadata addresses are refused. This applies to numeric addresses, unusual IPv4/IPv6 spellings, DNS answers and redirect destinations. The connection is pinned to the verified DNS addresses so a second lookup cannot redirect the socket to a private address. A public-looking name is not sufficient evidence that its resolved address is safe. The same transport protects robots requests and the actual file download.
A file can redirect at most five times. Every hop is checked before a connection, and each new origin has its own robots check. The actor follows normal public redirects without adding authentication. It retains the requested URL in input and the final file URL in sourceUrl, with redirect evidence where applicable. If the final destination is private, robots-disallowed or inaccessible, the result is a free error and the last known good downstream record should remain intact.
The download cap is checked against Content-Length when available and against received bytes while streaming. The streaming check is essential: a server may omit the header, advertise a compressed size or provide an incorrect length. The bounded downloader handles bytes directly. It does not run a binary document through a text decoder and then attempt to reconstruct it. All parsers receive the exact downloaded binary buffer after transport-level decompression.
Robots is checked per origin. A404 robots response means no published rules were found; it is not a copyright license. A disallow rule prevents the file request. Invalid, unavailable or blocked robots does not trigger a permissive fallback. File access401/403 is not bypassed. Requests, redirects, retries and robots retrieval share a maximum rate of one request per second per host. Providing more URLs does not increase per-host concurrency.
PDF-specific bounds: at most5 source files,25 pages per complete document and125 candidate pages in the input product. A PDF download is at most10,000,000 bytes, and total run downloads including robots/retries are at most50,000,000 bytes. maxTextChars is at most200000 per document, counting extraction separators before final trimming. The serialized result must fit2,000,000 bytes.
The parser runs in a separate bounded worker for each document, for at most60 seconds and never beyond the remaining work deadline. A worker timeout rejects the incomplete document and produces no result event. Files are handled in sequence; a later failure does not retroactively turn an earlier complete document into a free unit or delete its output.
Content-Type must be application/pdf or application/octet-stream, and the bytes must start with the PDF signature. Octet-stream support accommodates ordinary direct-download servers; it is not an instruction to parse arbitrary HTML as PDF. An HTML viewer, access-denied page or cloud preview must be replaced with an authorized direct PDF download URL.
The parser receives a byte array with evaluation disabled. It does not receive the file URL as a resource base, use a viewer scripting manager or follow embedded attachment and document links. The actor extracts bounded metadata fields but does not treat their content as commands, file paths or instructions to contact another service.
R6. Real happy, partial and failure output
The examples below are dataset rows from private acceptance runs executed on Apify infrastructure on 2026-09-05 with the deployed build and the live tariff. They are unedited. The source files are the hosted Wave A fixtures (syntheticFixture:true), generated with fixed control phrases rather than customer material.
The first JSON block contains the literal production prefill. The blocks after it are the actual rows of the accepted runs, one run per fixture: Example A is the paid complete document, Examples B, C and D are the three free notices.
Every row uses the common envelope: input identifies the request; sourceUrl identifies the response used; found identifies a useful complete paid unit; status gives the domain outcome; resultCount is one for that unit and zero for a notice. error is empty for useful completion and clean absence. It is nonempty for transport, access, format, parser and resource failures. warnings can describe limitations without converting a complete unit into an error.
The row-level partial flag belongs to that row, while OUTPUT.partial describes the run. A run can be partial even though an earlier complete row has partial:false. Do not overwrite the status of a valid delivered unit just because another file failed or remained unprocessed. Equally, do not call the run complete just because one row has found:true. This distinction is what allows a batch workflow to retain useful work while retrying only the missing portion.
{"fileUrls": ["https://api.apify.com/v2/key-value-stores/b0cgFsJRqVv3XOZyG/records/pdf-text.pdf"],"maxPages": 25,"maxTextChars": 200000}
Example A — complete digital-text PDF, paid (result-found counted once). Run GtMD6KgHhXMut5HHG.
{"input": "https://api.apify.com/v2/key-value-stores/b0cgFsJRqVv3XOZyG/records/pdf-text.pdf","sourceUrl": "https://api.apify.com/v2/key-value-stores/b0cgFsJRqVv3XOZyG/records/pdf-text.pdf","found": true,"status": "ok","resultCount": 1,"partial": false,"error": "","warnings": [],"checkedAt": "2026-09-05T17:57:08.535Z","schemaVersion": "1.0","documentId": "06b61092dfce5a841f53cad1bd5ddb045e32686f5ce57dc2ca40ef4f2bc96d2a","sha256": "06b61092dfce5a841f53cad1bd5ddb045e32686f5ce57dc2ca40ef4f2bc96d2a","pageCount": 2,"pages": [{"pageNumber": 1,"text": "WAVE-A PAGE ONE MARKER","charCount": 22},{"pageNumber": 2,"text": "WAVE-A PAGE TWO MARKER","charCount": 22}],"metadata": {"Title": "Original Wave A synthetic fixture","Author": "Tim Zinin / Wave A","Subject": "unspecified","Keywords": "","Creator": "anonymous","Producer": "ReportLab PDF Library - (opensource)","CreationDate": "D:20000101000000+00'00'","ModDate": "D:20000101000000+00'00'","PDFFormatVersion": "1.3"},"requiresOcr": false,"syntheticFixture": true,"redirectChain": []}
Example B — valid PDF without extractable text, free not_found. Run jChC23r2jngkUujT7.
{"input": "https://api.apify.com/v2/key-value-stores/b0cgFsJRqVv3XOZyG/records/pdf-blank.pdf","sourceUrl": "https://api.apify.com/v2/key-value-stores/b0cgFsJRqVv3XOZyG/records/pdf-blank.pdf","found": false,"status": "not_found","resultCount": 0,"partial": false,"error": "","warnings": [],"checkedAt": "2026-09-05T17:57:14.119Z","schemaVersion": "1.0","documentId": "ad13559e65e5c84a4a78c8aaabee5962a6fd0df4ae24af8aae1d368ba88aacf3","sha256": "ad13559e65e5c84a4a78c8aaabee5962a6fd0df4ae24af8aae1d368ba88aacf3","pageCount": 1,"pages": [],"metadata": {"Title": "Original Wave A synthetic fixture","Author": "Tim Zinin / Wave A","Subject": "unspecified","Keywords": "","Creator": "anonymous","Producer": "ReportLab PDF Library - (opensource)","CreationDate": "D:20000101000000+00'00'","ModDate": "D:20000101000000+00'00'","PDFFormatVersion": "1.3"},"requiresOcr": false,"syntheticFixture": true,"redirectChain": []}
Example C — image-only scan, free requires_ocr notice. Run 8gyQq16LSKNgaKA9z.
{"input": "https://api.apify.com/v2/key-value-stores/b0cgFsJRqVv3XOZyG/records/pdf-scan.pdf","sourceUrl": "https://api.apify.com/v2/key-value-stores/b0cgFsJRqVv3XOZyG/records/pdf-scan.pdf","found": false,"status": "requires_ocr","resultCount": 0,"partial": false,"error": "","warnings": ["An image-only page has no extractable text layer; use OCR. No document result is charged."],"checkedAt": "2026-09-05T18:51:18.790Z","schemaVersion": "1.0","documentId": "de3093843a22846aba9c1fa1e68b55a6959492eb25373a4329051b3d356a9398","sha256": "de3093843a22846aba9c1fa1e68b55a6959492eb25373a4329051b3d356a9398","pageCount": 1,"pages": [],"metadata": {"Title": "Original Wave A synthetic fixture","Author": "Tim Zinin / Wave A","Subject": "unspecified","Keywords": "","Creator": "anonymous","Producer": "ReportLab PDF Library - (opensource)","CreationDate": "D:20000101000000+00'00'","ModDate": "D:20000101000000+00'00'","PDFFormatVersion": "1.3"},"requiresOcr": true,"syntheticFixture": true,"redirectChain": []}
Example D — 26-page document above maxPages=25, free limit_exceeded notice. Run 2K9lyWwhyslzhEJa2.
{"input": "https://api.apify.com/v2/key-value-stores/b0cgFsJRqVv3XOZyG/records/pdf-26-pages.pdf","sourceUrl": "https://api.apify.com/v2/key-value-stores/b0cgFsJRqVv3XOZyG/records/pdf-26-pages.pdf","found": false,"status": "limit_exceeded","resultCount": 0,"partial": true,"error": "PDF has 26 pages; maxPages=25","warnings": [],"checkedAt": "2026-09-05T17:57:19.132Z","schemaVersion": "1.0","documentId": "13e40427f85a42c71127a5d5b7bf32d7d2fc36469557970f9808ea38c94b0f8b","sha256": "13e40427f85a42c71127a5d5b7bf32d7d2fc36469557970f9808ea38c94b0f8b","pageCount": 26,"pages": [],"metadata": {},"requiresOcr": false,"syntheticFixture": true,"redirectChain": []}
R7. Field dictionary
input
string: requested normalized file URL, preserved even after redirects. Keep it with the task input; it is not necessarily the final download address.
sourceUrl
string: final public response URL used by the parser, or requested URL when no response was available. Treat query strings as potentially sensitive provenance.
found
boolean: true only for one complete useful paid unit. A row can exist with found:false because free explanations also use the dataset.
status
string: domain outcome listed below. Consumer routing should check status together with found, partial and error.
resultCount
integer: one for a complete useful unit, zero for a free notice. It is not the number of pages, words, sheets or cells nested in that unit.
partial
boolean: this row describes an incomplete observation or a limit. The run can still be partial while a particular completed row is not.
error
string: empty on useful completion and clean absence; nonempty on access, transport, format, resource or parsing failure. Do not erase it during export.
warnings
array of strings: bounded explanatory limitations or source details. A warning does not by itself imply a failed or billable record; inspect the documented outcome.
checkedAt
ISO8601 UTC string: time the actor produced this observation, not source creation/publication time or a certification of freshness.
schemaVersion
string: currently1.0. Use it when validating downstream shapes and retain the actor build identifier alongside your export.
syntheticFixture
boolean: whether the supplied source belongs to our named hosted fixture prefix. An arbitrary customer document is not synthetic simply because it contains the same marker.
documentId and sha256
Both identify the exact downloaded PDF bytes with a lowercase64-character SHA256 hash after a valid MIME/signature check. They are null when a source or initial format refusal prevented that step. Regenerating a visually identical report can change its hash because metadata, compression or object numbering changed. Use a separate normalized-text comparison if you want to suppress purely container-level revisions.
pageCount
The parser's total physical PDF page count, including blank pages. It is not the number of pages with text. A26-page limit notice can report pageCount26 while pages is empty because no incomplete document result is released. Source/MIME/early parse failures can leave pageCount null.
pages
An ordered array on a complete digital result, containing objects with pageNumber, text and charCount. pageNumber is one-based and refers to the physical PDF page, not a printed page label such as iii, A-1 or an offset printed in a report footer. Empty physical pages can remain in a complete text-bearing document with empty text; their numbers are not renumbered away.
text is normalized extraction text, with engine item separators and line boundaries. It is not HTML or Markdown, and it does not promise the original visual reading order. charCount is the JavaScript string length of the returned text, not a UTF8 byte count, grapheme count or billable quantity. The text budget is checked during extraction, including separators that can later be trimmed.
metadata
An object containing available string values from a bounded whitelist: Title, Author, Subject, Keywords, Creator, Producer, CreationDate, ModDate and PDFFormatVersion. Each value is capped2048 characters. Missing fields are omitted. PDF date strings are retained as source metadata and are not silently converted into verified publication dates or author identities.
requiresOcr
A boolean routing hint. True means at least one textless page contains an image-paint operation and the extractor cannot provide a complete digital-text document. The actor returns requires_ocr for free with no paid pages array. This is a practical extraction boundary, not a classifier that can prove whether a bitmap contains readable words. Blank pages with no image painting produce a different result.
redirectChain
An array of encountered public redirects with url, HTTP status and location. sourceUrl identifies the final response. A refused redirect can leave a partial chain in a free error notice. Redirect hops do not become document units and do not receive their own result events.
R8. Evidence and boundaries
Binary fixtures are generated from original Wave A content and stored beside MANIFEST.sha256. The manifest describes file bytes, not a file name, upload timestamp or browser rendering. SHA256 changes if a PDF producer or ZIP container changes metadata even when the visible words look identical. For exact regression evidence, compare hashes before comparing parsed results. For content-level business deduplication, use your own normalized-content policy in addition to the actor's byte identity.
For a customer source, save the requested URL, final URL, checkedAt, SHA256, input caps and parser build together. checkedAt records this actor's observation time; it is not the document's publication time or the date a statement became true. Metadata dates are source-controlled strings and may be missing, ambiguous or incorrect. File accessibility today does not establish that the file is current, complete or approved for the buyer's particular use.
Local tests exercise real parser or binary-engine behavior and the actual SDK charging manager at controlled storage/charge boundaries. The local HTTP proof exercises the actual production normalizer and downloader with an explicit test DNS mapping. Neither substitutes for a deployed Apify run; that evidence comes from the accepted platform runs listed in R4, which exercised the built container, platform permissions, memory, execution limits, installed dependencies, chargedEventCounts and source access from platform IPs.
For each accepted build, retain at least one useful output, one exact clean negative, one resource-limit notice and the associated OUTPUT summary. Preserve error text rather than replacing it with a generic empty document label. This evidence makes regressions diagnosable: a parser change, altered bytes, expired URL and changed input limit can all produce different observations without having the same root cause.
The prefill is a synthetic daily regression source and is marked as such. It does not prove performance on arbitrary customer documents or replace a permitted real-document canary. The same is true of easy printed markers: recovering a marker shows that a path worked on those bytes, not that the engine achieves a measured accuracy percentage on every language, producer, layout or image quality.
The locally pinned dependency is pdfjs-dist4.10.38 through its legacy Node build. Canvas is omitted because no page is rendered. The library can print warnings about missing rendering polyfills during initialization; the actual local proof establishes that text extraction and image-operator scan detection work without those rendering facilities. Those warnings do not justify claiming an untested raster capability.
The scan fixture is generated as one raster image placed on a PDF page, with the visible phrase drawn into pixels. The blank fixture is a valid page with no text. The26-page fixture is structurally valid and contains generated markers, so its limit result proves a page-boundary refusal rather than merely a parser error on corrupt bytes.
R9. Decision routing
Route a row to your useful-results branch only when found is true, resultCount is one and error is empty. Apply the domain completeness rules below before merging its nested data into a canonical table or search index. Preserve provenance at the destination. A consumer should be able to trace a single derived text fragment or cell back to its input file, page or sheet and the run that produced it.
Route a clean absence to an observation log. It means no useful content was produced within this actor's supported operation on those bytes. It does not mean a business entity is absent, a file is legally empty, or a customer has no data. Do not replace a previous successful document with empty data solely because a later URL returned a notice; compare the byte identity, source status and run completeness first.
Route a source or parser error to a retry or review queue with the original reason. A temporary network outage can justify a bounded later retry, whereas a password requirement, unsupported format or hard size limit needs a changed input or a different supported workflow. Retrying identical unsupported bytes every minute adds work without addressing the refusal. Keep the last good result until a verified replacement is available.
Route partial runs using OUTPUT.unprocessed and the domain counters. A cap can leave an input unprocessed, or a parser can reject the whole oversized unit after inspecting it. These are different from a complete negative. Split a large batch at the input-file boundary, preserving the input list and already delivered identities. Do not blindly rerun the entire batch unless repeated delivery and possible repeated billing are acceptable.
Route a fatal budget, pricing, storage or charge error to an operator. Those failures concern delivery integrity rather than the contents of a source document. Reconcile billed event counts and dataset contents before resuming. A workflow that checks only the process status will miss uncertain writes; a workflow that checks only dataset length will miss pricing failures or incomplete batches.
For status=ok, require pages.length to match pageCount before your importer creates page records. Preserve empty page entries if your application needs exact physical references. For status=not_found, record a valid PDF with no extracted text or image-only-page indication. For status=requires_ocr, route the original authorized file to a separate OCR process, retaining its hash so the two observations can be linked.
For status=limit_exceeded, reduce or prepare the source at an authorized upstream step. Lowering maxPages below the actual count cannot make the extractor return a prefix; it causes whole-document refusal. For password_required, obtain an authorized unencrypted version through the source owner's normal process. No password list or cracking option exists in this input contract.
R10. Commercial playbooks
For a recurring ingestion service, separate acquisition from conversion. The source owner publishes an authorized direct file URL; your existing workflow supplies that URL to the actor; a staging step validates the complete result; the final step updates your own application. Keep responsibility for source permission, file retention and downstream review explicit. The actor performs the bounded transformation and exposes evidence, while your application owns the business decision.
For a client delivery, agree on the supported file types, unit, limits and definition of completeness before running a large batch. Quote extraction separately from your own interpretation and quality review. A reliable conversion can still require manual decisions about reading order, headers, dates, confidence or source changes. The actor does not promise income, a specific time saving or correctness of decisions made from extracted content.
Use a representative pilot set that includes normal files and known difficult cases. Count clean successes, useful-but-reviewable observations, limits and outright failures separately. Include setup, failed attempts and manual review when assessing your own workflow cost. Selecting only the easiest fixture results would conceal the operational work required for a real archive or reporting process.
For repeated snapshots, store both the source-byte hash and a business-level comparison key. A file can be regenerated with new metadata and identical useful content; conversely, a stable URL can serve materially changed content. Decide which difference matters before sending alerts or replacing records. Keep source changes distinct from parser-version changes by pinning the actor build for comparison periods.
Playbook1: searchable internal reports. Publish your generated reports to an authorized direct file endpoint, run a small batch, and create one parent document keyed by SHA256. Expand pages into a child table that retains physical pageNumber. Index the text while keeping the parent URL and observation time. A search hit can then cite a specific physical page without asserting that the actor reconstructed the original layout.
Playbook2: archive preparation queue. Supply a bounded list of files from an archive you control. Route complete digital PDFs to import, blank outcomes to an inspection list and requires_ocr files to a separate OCR queue. Route password and limits back to document preparation. This gives the operator actionable distinctions instead of a single bucket of empty strings; it does not automate permissions or manual document review.
R11. Integration recipes
Use the actor through the normal Apify API or SDK. Supply the same JSON input you tested in the Console, set a suitable timeout and memory allocation, and use a maximum total charge limit appropriate for the unit price. Store your API token in your workflow's credential store or environment, not in shared source files, URLs inside documents or copied README examples. Consult the official Apify run API for the current request and authentication details.
An asynchronous integration starts a run, stores its ID and waits for a terminal result before reading the dataset. A platform webhook can notify an existing endpoint that a run finished; the webhook payload is an event, not the converted document. Retrieve the default dataset and OUTPUT summary for the specific run identified in that event. Verify the run ID and deduplicate webhook delivery because webhook redelivery should not repeat your downstream insertion.
In n8n, a practical sequence is a scheduled trigger or authorized file-list source, an Apify run step, a wait/poll step, dataset retrieval and a conditional branch on found/status/error. Follow that with a staging table or document store. Use the run ID as the workflow correlation key. Keep the token in n8n credentials and avoid logging the entire signed source URL when your workflow distributes logs beyond the people who can access the file.
Treat one dataset record as the parent record. When you flatten its nested arrays into child tables, copy the file identity, sourceUrl, checkedAt and relevant page/sheet/row coordinates into every child. Store a child identifier that is stable within that conversion. Flattening for analysis does not create extra actor result events, and counting flattened rows is not a way to calculate the actor invoice.
JSON is the authoritative export for nested and typed results. CSV exports can serialize arrays into a cell and spreadsheet tools can reinterpret leading zeros, date-like strings or long numbers. If a downstream tool needs a flat CSV, build it from a validated JSON result with explicit column types and escaping. Keep the original JSON next to the derived file so a reviewer can distinguish actor output from export-time coercion.
Before an automated merge, validate both shape and outcome. Reject records with nonempty error from the success branch, inspect warnings according to your quality policy and verify required domain fields. Commit the merge only after the unit's completeness requirements pass. If a later run fails, record that attempt separately and preserve the previous successful content rather than interpreting the failure as a deletion.
For large result exports, use the platform's normal dataset pagination and store each page under the same run identifier. Page retrieval is a read of an already created dataset, not a new conversion run. Starting another actor run to recover an export download can cause repeated conversion and billing. Retry the export operation against the existing dataset when the actor run itself was already complete.
Separate transport retries from business retries. The actor already performs a bounded retry for eligible source failures. Your orchestrator can perform a later retry when the source is expected to recover, but it should record why that retry was scheduled and which inputs were not delivered. Never let both layers recursively retry an entire batch without a total attempt limit and an explicit treatment of already delivered units.
A relational representation can use documents(documentId, sourceUrl, checkedAt, pageCount) plus document_pages(documentId, pageNumber, text, charCount). Use(documentId,pageNumber) as the child key within one extraction contract. If your parser build changes, retain its build identifier so you can compare extraction revisions without confusing them with a change in file bytes.
For a text-search service, chunk text inside each returned page after the document passes completeness validation. Add your chunk index as a downstream field, retaining the parent document hash and pageNumber. The actor's document price does not depend on how many chunks you create later. Do not present downstream chunking or embedding as an actor capability when those steps belong to your own pipeline.
R12. Operating guide
Files are processed sequentially to keep peak memory and request pressure bounded. The actor does not launch a separate browser per file, enqueue an unbounded crawl or parallelize all supplied documents. More input URLs can increase total work and the chance of reaching the240-second work deadline; it does not create unlimited processing time. The platform run timeout is300 seconds, leaving time to record a summary and close the SDK.
Source requests have their own bounded timeout and at most two retries, only for eligible network failures,429 and server errors. Backoff is at least one second and then three seconds; Retry-After is respected when it fits within the remaining deadline. Empty success responses, unsupported bytes and normal4xx format/access failures are not repaired by repeated downloading. A deadline-limited retry leaves an explicit error instead of silently substituting fixture data.
There is no cross-run cache that can be assumed to suppress a result event. Deduplicate your file list before scheduling if repeated conversion is unnecessary. Use source revision identifiers or your own prior hashes where you already possess the file bytes. Be careful with expiring links: two different signed URLs may refer to the same file, while one stable URL may return a new revision. The actor cannot infer your business retention or replay policy from URL spelling alone.
Monitor the OUTPUT counters and free notices alongside charged event counts. A rising limit rate can mean your documents changed shape or size. A rising source-error rate can mean access restrictions, expired links, robots changes or an outage. A drop in useful outputs with stable HTTP success can mean unsupported content rather than a network failure. Inspect a representative affected file and change one cause at a time.
Before upgrading the actor build used by a schedule, replay your approved regression inputs against the new build under a small budget. Compare source hashes, domain fields, useful-unit counts and exact negative semantics. Keep the previous output export and build identifier so a changed reading order, date representation or OCR word segmentation is distinguishable from an upstream content change.
Run logs and datasets can contain source URLs and extracted content. Choose access permissions and retention periods appropriate for those materials. Temporary parser files are implementation scratch space, not a backup of the source archive. Keep source originals in your own authorized storage if you need them for a later audit. Deleting a local temporary file does not delete an already exported dataset or a downstream copy.
A complete local test suite verifies defined boundaries, but ongoing production monitoring is still necessary. Recheck the default source, MIME and SHA after fixture hosting changes. Recheck container dependencies and resource usage after a build change. Platform memory or engine changes can affect startup cost even if the same marker still appears in output; cost conclusions need measured platform runs, not a developer-laptop timing.
Avoid rerunning the same oversized PDF with an unchanged maxPages limit. A26-page source will continue to receive a free limit notice at25; processing more small batches does not alter the file's physical page count. If authorized, prepare separate complete documents upstream and keep an explicit mapping back to the original report so page references are not lost.
Some PDF producers place characters in drawing order rather than natural reading order, use custom encodings or omit the mappings needed for meaningful Unicode extraction. A file can contain visible text and still produce garbled or surprising text without being a transport failure. Compare a representative result with the original document before using it in a high-volume text index.
R13. FAQ
Where should I report a reproducible issue? Use the actor's Store Issues channel after publication, with the run ID, actor build, relevant input limits, status/error and a minimal file you have permission to share. Do not post passwords, API tokens, confidential extracted text or active signed URLs in a public issue. If the document cannot be shared, provide a sanitized original fixture that reproduces the same parser behavior.
Does a public URL prove authorization? No. You are responsible for ownership, permission and downstream use. A robots allow rule concerns crawler access, while copyright, confidentiality and source terms concern other obligations. This product does not grant a license to redistribute an archive or access content behind a login. It processes the public file routes you supply under the documented network and format restrictions.
Why did I receive a free row instead of useful text or cells? Read status and error together. Clean absence has an empty error. A resource, format or transport refusal has a reason. The notice exists so your workflow can distinguish an empty supported input from an unsuccessful attempt. Removing that distinction would make failed imports look like intentional empty data.
Can I increase the limit beyond the form maximum? No. Runtime validation enforces the same hard caps even when input is sent directly through the API. Split documents at an authorized preparation step, reduce the batch or choose a product with a larger documented contract. A larger monetary cap does not disable byte, page, cell, pixel or deadline limits.
Will a repeat run be free because the URL is unchanged? No. This actor has no persistent cross-run replay ledger. Repeating a successful conversion can create another result event even if the URL or file hash is unchanged. Reuse an existing dataset for another export, or implement deduplication in your own workflow if your use case needs it.
Is confidence or a successful parse a guarantee of correctness? No. Structured output means the engine completed the documented operation on the received bytes. It does not certify the source statement, file author's intent, financial totals, legal interpretation or downstream business decision. Apply your domain's review requirements before making consequential decisions from extracted content.
Is this page a guarantee of platform cost or availability? No. The prices above were read back from the deployed tariff on 2026-09-05 and the examples come from accepted platform runs of the same build; check the tariff shown on the Store page before a large run, because a tariff change is an operator action, not something inferred from this text.
Does it run OCR on scanned pages automatically? No. requires_ocr is a free routing result. The actor does not substitute a remote OCR or language model, charge for hidden page work or invent text from an image. Use the original file in a separately authorized OCR workflow.
What happens when only one page in a digital document is a scan? The document is incomplete for this extractor's paid unit. It returns requires_ocr and does not bill a partial digital-text document. The array of complete pages from an earlier different file can remain delivered; that is a separate unit.
Can I get just the first25 pages from a longer file? No. maxPages is an acceptance limit for a complete document. A larger document yields a free partial limit notice with its known page count. This avoids describing a prefix as the whole source.
Are PDF page labels and text positions preserved? Physical one-based page numbers are preserved. Printed labels, coordinates, font styles, columns and table cell geometry are outside this output contract. A table can become plain text in an order that needs review.
Can I supply a password I already know? This version intentionally has no password input. Password-protected sources receive a free error. Prepare an authorized unencrypted copy using the document owner's normal process rather than attempting repeated guesses.
R14. Sources, rights and support
Process only documents and images you own or are authorized to transform. Retain applicable notices, attribution and confidentiality restrictions in derived data. Conversion into JSON does not remove copyright or make private information public. Avoid redistributing a source archive just because the input was technically accessible through a public download link.
The original Wave A fixtures are generated for testing and include fixed control phrases rather than customer material. Their syntheticFixture flag identifies that origin in hosted examples. Production URLs, parser outputs and source content are treated as data, never as instructions to execute code or request unrelated resources.
The actor uses the platform's existing dataset, key-value store, API, schedule and webhook capabilities. It does not contact people, submit forms, bypass a login, create external documents or modify the input source. Those actions, if required by a customer workflow, remain separate authorized steps owned by that workflow.
Parser reference: PDF.js document initialization and text API. The shipped exact dependency is pdfjs-dist4.10.38 under Apache2.0; its package metadata and installed source were inspected for Node20 compatibility and data-only extraction. The extraction options disable generated-code evaluation, and no PDF viewer or JavaScript action execution path is instantiated.
Binary fixtures use original control text, ReportLab for deterministic PDF construction and Pillow for a locally generated scan bitmap. Those generators are build tools, not production download dependencies. The production actor fetches authorized file bytes, checks caps and extracts bounded text; it does not download somebody else's sample as the default or upload fixtures during construction.
Related-tool links below point only to published actors of the same author. The output examples above are accepted platform rows, not local fixture output.
Related tools
Related tools for adjacent workflows in data pipelines for AI applications.
| Actor | What it does |
|---|---|
| RAG Dataset Builder | Pair it in the data pipelines for AI applications workflow: Turn buyer-authorized public website sitemaps into bounded, source-linked text chunks for RAG, search,... |
| Structured Data Extractor | Pair it in the data pipelines for AI applications workflow: Extract title, meta, JSON-LD, headings, links, emails, and price observations from up to 100 authorized... |
| Live Price Oracle | Pair it in the data pipelines for AI applications workflow: Get timestamped DexScreener market observations for up to 100 token contracts or bounded ticker searches |
| URL to Markdown Converter | Pair it in the data pipelines for AI applications workflow: Convert up to 100 authorized public HTML pages into clean Markdown for RAG, AI agents, SEO research, and... |