# Datasheet Parser (`leonyu/datasheet-parser`) Actor

Parse component datasheet PDFs (your uploads or manufacturer links) into normalized spec JSON — max ratings, electrical characteristics, pinout, ordering codes — with page-level citations and OCR.

- **URL**: https://apify.com/leonyu/datasheet-parser.md
- **Developed by:** [Leon Yu](https://apify.com/leonyu) (community)
- **Categories:** Developer tools, AI
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 50.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 datasheet parseds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What does Datasheet Parser do?

**Datasheet Parser** turns a component datasheet PDF into normalized spec JSON. You supply the file, either by upload or by a **direct http(s) link** such as the manufacturer's own PDF. The Actor reads absolute-maximum and electrical tables, pinouts, and ordering rows, and every value cites the **file and page** it came from.

It does not search the web, and it does not open datasheet aggregator sites (AllDataSheet, Datasheet4U, and the rest of the block list). An HTML catalog page is rejected instead of being crawled for more links.

Full page text is **off by default**. The dataset gets structured fields and a short provenance snippet. Turn on `includePageText` only when you have the right to store the datasheet prose.

### Why use Datasheet Parser?

Hardware engineers, component buyers, and BOM or PLM teams keep retyping the same limits out of PDFs. The public request shows up in places like [r/AskElectronics](https://www.reddit.com/r/AskElectronics/comments/18fw19z/data_sheet_assistant_for_electronics_engineers/) and [Hacker News](https://news.ycombinator.com/item?id=47031293). Store Actors that parse datasheets today are single-vendor (for example a Rockwell-only parser).

This Actor is vendor-agnostic:

- Digital PDFs are read with PyMuPDF table finding, with a text-layout fallback when the page has no ruling lines.
- Scanned pages go through Tesseract OCR. English traineddata is in the image.
- Original numbers and units are kept, and an SI `normalizedValue` is added (volts, amperes, ohms, farads, hertz, watts, seconds, and kelvin for °C).
- A bad file becomes an `error` item and is not charged. The rest of the run continues. If every input fails, the run itself fails.
- Scheduling, the dataset API, and key-value storage come from the Apify platform. There is no browser. Apify Proxy is not used.

### What data can it extract?

| Field | What it is |
| --- | --- |
| `identity` | Manufacturer, part numbers and ordering codes, series, description, packages, RoHS, REACH, revision, revision date. Each value has a provenance object. |
| `specifications` | Rows of parameter, symbol, conditions, min, typ, max, unit, SI `normalizedValue`, `footnoteRefs`, `unitMissing` when a number has no unit, `relativeLimits` when a limit is a rail offset rather than an absolute number, and provenance. |
| `pinout` | Pin number, name, and function when a pin table is present. |
| `ordering` | Ordering code, package, packing, RoHS. |
| `operatingTemperature` / `supplyVoltage` | Ranges from a labeled sentence, or from a matching spec row. |
| `status` | `ok`, `partial`, or `error`, plus `errors` and `warnings`. |
| `category` | `auto` guess (MOSFET, diode, regulator, capacitor, resistor, connector, sensor, MCU, IC, other) or your hint. |

### How to parse a datasheet

1. Open the Actor and set the run memory to **512 MB** (the recommended size; the Actor allows 512–4096 MB) and the timeout to **300 seconds**.
2. Add datasheets in one of two ways. Paste a direct PDF URL into **Datasheet URLs**, or use **Datasheet files** to upload a PDF, a PNG/JPEG scan, or a ZIP of those. A bare key such as `nw3401n.pdf` is also accepted when that record already exists in the run's default key-value store. The Console file picker stores the upload and passes its record URL.
3. Leave **Include full page text** off unless you need the prose. Leave the LLM switch off unless you want empty identity fields filled with your own API key.
4. Run the Actor and open the dataset. Use the Overview, Specifications, Pinout, and Ordering views, or download JSON, CSV, or Excel.

An input that matches the synthetic fixture is in [`examples/input.json`](examples/input.json). The output below is a real parse of that fixture, not a mock. The full item is [`examples/output.json`](examples/output.json).

### How much does a datasheet parse cost?

The published pay-per-event prices are **$0.02 per parsed file** and **$0.002 per OCR page**. A download or parse that fails is **not** charged the per-file event, and its OCR pages are not charged either. The code records event names only after a file produced identity or table data. Dollar amounts live in the Apify Console, not in the request.

| Event | When it is charged | Price |
| --- | --- | --- |
| `datasheet-parsed` | Once per file whose status is `ok` or `partial` and that produced identity or table data. This is the primary event. | $0.02 |
| `page-ocr` | Once per page that Tesseract actually read, and only on a file that was charged as `datasheet-parsed`. | $0.002 |

`Actor.push_data` is called **without** a charge event. Do **not** leave the synthetic `apify-default-dataset-item` event enabled, or every dataset row is billed again on top of `datasheet-parsed`. Remove that event in the Console monetization settings.

Do not charge `apify-actor-start` from code. If you keep that synthetic event, Apify covers the first 5 seconds of compute (once, up to and including 1 GB). A single digital datasheet finishes inside that window. A batch of scanned pages does not, which is why `page-ocr` exists.

Error files (unsupported type, blocked host, HTTP 403, timeout, empty archive) are pushed so you can see what failed. They are **not** charged.

Measured cost is in [Runtime and memory](#runtime-and-memory). Price each event at **at least 3×** the compute it causes. You receive 80% of event revenue, so a list price of about **3.75×** compute is what leaves you 3× compute after Apify's share.

### Input

See the Input tab for every field. The limits default to 10 files, **120 pages**, and 20 MB per file. `auto` category includes op-amp as well as diode, MOSFET, regulator, and the other families in the list.

`datasheetUrls` accepts a URL string or `{ "url": "https://..." }`. Custom headers and cookies are ignored. Only `http` and `https` are fetched, one file per URL, over HTTP/1.1, with a short redirect cap. DNS, TCP connect, TLS, redirects, the body, and retries share **one 20 second wall-clock deadline**. The socket is closed when that deadline passes, including when the peer trickles bytes. Each resolved address gets at most 5 seconds to connect and finish TLS, so a blackholed address cannot stack its own timeout on top of the next one, and the total of every address, redirect, and retry still stays inside 20 seconds. HTTP 401, 403, and 451, and a connection reset, fail immediately and are not retried. A 403 says the site blocks cloud and datacenter IPs and that you should upload the PDF. Private, loopback, and link-local addresses are rejected, including after DNS. Aggregator hosts are rejected before the request is sent.

The platform run timer also includes container startup and shutdown. A download that uses the full 20 seconds often shows a run of about 28–30 seconds. That extra time is outside the download deadline.

Some manufacturer sites block cloud and datacenter IP addresses. **st.com** often times out. **onsemi.com** often answers **HTTP 403**. For those hosts the Actor logs an upload hint before it starts the download. Upload the PDF with **Datasheet files** instead of pasting the URL. The failed download is an error item and is not charged. `OUTPUT` and `SUMMARY` list each failure with a category and the domain: `blocked` (HTTP 401, 403, 451, a connection reset, or the cloud-IP block note), `timeout`, `invalid_input`, `parse_error`, or `other`. The same line is the run status message. It names the domain and the file name, not the full URL or the query string.

Each PDF record includes `pagesProcessed` and `pagesTotal`. The default of 120 pages is enough for the 68-page TI LM358 and the 55-page ST L78 at the recommended 512 MB (measured peak RSS on those files is about 130 MB, and reading 120 text-layer pages stays well under that memory cap and the 300 second run timeout). If the file is longer than `maxPages`, status is `partial`, and `warnings` includes `Truncated PDF: processed N of M pages (pagesProcessed=N, pagesTotal=M)`. Raise `maxPages` (maximum 200) to read the rest. A fully scanned file is slower because OCR runs per page; lower `maxPages` for those.

**Proxy** (`proxyConfiguration`) is **off by default**. Apify Proxy is not supported and is ignored with a warning; upload the PDF when a site blocks the download. Advanced users can pass their own proxy in *Custom proxy URLs*. The Actor never enables a proxy on its own.

`componentCategoryHint` = `auto` scores the first pages. Any other allowed value is stored as `category`, and the guess is still returned as `detectedCategory`.

`normalizeUnits` (default on) writes `normalizedValue` in SI and leaves `min` / `typ` / `max` / `unit` as printed.

A limit printed as an offset from a rail, such as `VS – 1.5 V` or `(V+) – 1.5`, is not stored as the absolute number 1.5. `min`, `typ`, and `max` stay null for that column. `relativeLimits` holds the raw text, the rail name, and the signed offset:

```json
"relativeLimits": [
  { "role": "min", "text": "VS – 1.5", "reference": "VS", "offset": -1.5 }
]
```

`role` is the column the expression sits in (`min`, `typ`, or `max`). `offset` is volts in the row's unit, negative when the rail is reduced. `(V–)` with no number is `{ "reference": "V-", "offset": 0 }`.

`useLlm` is off by default. When you enable it and pass `llmApiKey`, the Actor sends only the empty manufacturer, series, and description slots plus the part numbers it already extracted. It does not upload the datasheet. A missing key is a warning, not a failed run. Extracted values are never overwritten.

### Output

You can download the dataset as JSON, CSV, Excel, or HTML. One item per file:

```json
{
  "sourceName": "nw3401n.pdf",
  "status": "ok",
  "category": "MOSFET",
  "partNumber": "NW3401N",
  "identity": {
    "manufacturer": {
      "value": "Northwind Semiconductor",
      "provenance": { "file": "nw3401n.pdf", "page": 1, "snippet": "Manufacturer: Northwind Semiconductor" }
    },
    "revision": { "value": "C", "provenance": { "file": "nw3401n.pdf", "page": 1, "snippet": "Revision: C" } }
  },
  "specifications": [
    {
      "table": "absolute_maximum_ratings",
      "parameter": "Drain-source voltage",
      "symbol": "VDS",
      "conditions": null,
      "min": null,
      "typ": null,
      "max": 60,
      "unit": "V",
      "normalizedValue": { "min": null, "typ": null, "max": 60, "siUnit": "V" },
      "page": 1,
      "provenance": { "file": "nw3401n.pdf", "page": 1, "snippet": "Drain-source voltage VDS 60 V" }
    },
    {
      "table": "electrical_characteristics",
      "parameter": "Drain-source on resistance",
      "symbol": "RDS(on)",
      "conditions": "VGS = 10 V, ID = 15 A",
      "min": null,
      "typ": 35,
      "max": 44,
      "unit": "mohm",
      "normalizedValue": { "min": null, "typ": 0.035, "max": 0.044, "siUnit": "ohm" },
      "page": 2,
      "provenance": { "file": "nw3401n.pdf", "page": 2, "snippet": "Drain-source on resistance RDS(on) VGS = 10 V, ID = 15 A 35 44 mohm" }
    }
  ],
  "pinout": [
    { "pin": "1", "name": "G", "function": "Gate", "page": 2, "provenance": { "file": "nw3401n.pdf", "page": 2, "snippet": "1 G Gate" } }
  ],
  "operatingTemperature": {
    "min": -55,
    "max": 175,
    "unit": "degC",
    "normalizedValue": { "min": 218.15, "max": 448.15, "siUnit": "K" }
  }
}
```

That JSON is abbreviated. [`examples/output.json`](examples/output.json) is the full item from the 10-page synthetic fixture (12 spec rows, 3 pins, 2 ordering codes). Snippets are capped at 180 characters and contact details in a snippet are redacted.

### Runtime and memory

Measured with `scripts/measure_cost.py` on the synthetic fixtures (Python 3.12, PyMuPDF 1.26, Tesseract 5.3). This is parse time inside one process. It does **not** include pulling the image or Apify container startup.

| Case | Time | Peak RSS | Compute at 512 MB and $0.20 / GB-hour | 3× that compute |
| --- | --- | --- | --- | --- |
| 10-page synthetic digital datasheet | 0.11 s | 91 MB | $0.0000031 | $0.0000094 |
| Vishay 1N4001, 5 pages | 1.3 s | 97 MB | $0.000036 | $0.00011 |
| TI LM358, 68 pages | 7.7 s | 128 MB | $0.00021 | $0.00064 |
| ST L78, 55 pages | 4.3 s | 124 MB | $0.00012 | $0.00036 |

These are in-process times on a fast CPU. Apify bills allocated memory for the whole run, including startup, so a 512 MB run costs about half of a 1024 MB run for the same wall time. Peak RSS stays near 130 MB, so **512 MB** is enough. A 1024 MB run does not make extraction faster. Use **300 seconds** so a few long datasheets, or a scanned file that really needs OCR, can finish. Blank pages are not sent to Tesseract. Table finding after the first pages runs only on pages that look like a ratings, pin, or ordering table.

Apify bills the **allocated** memory for the whole run, not the RSS. 512 MB is about 4× the measured peak and is the recommended run size (`minMemoryMbytes` is 512, `maxMemoryMbytes` is 4096). The $0.20 figure is the Starter plan compute-unit price; Scale is $0.16, so Starter is the conservative cost. With `apify-actor-start` enabled, the first 5 seconds at or below 1 GB are not billed as compute, so a one-file digital run is dominated by the start event ($0.00005 at the platform default) rather than by parse time. Use the per-page OCR number when a run will OCR more than a handful of pages.

### Limitations

- Some manufacturer sites block requests that come from a cloud or datacenter IP. st.com often times out (`timeout`). onsemi.com often returns HTTP 403 (`blocked`). The same link can work from a home network. Upload that PDF with the file input. A failed download is an error item, it is not charged, and the run summary names the category and the domain. Apify Proxy is not supported; your own proxy URL is optional.
- A run whose every input fails, or whose input is empty, ends as **FAILED**. The same summary is the status message and the key-value records `OUTPUT` and `SUMMARY`. A run that parsed at least one file stays **SUCCEEDED** and still lists the failures. One timed-out URL is FAILED because nothing was parsed; the download itself stopped at 20 seconds.
- `maxPages` defaults to 120. A longer PDF is truncated: `pagesProcessed` is how many pages were read, `pagesTotal` is how many the file contains, and the warning states both. `pageCount` remains the number of pages read.
- Extraction is deterministic and rule-based. Curves, graphs, mechanical drawings, and tables whose headers are not words like Parameter, Symbol, Min, Typ, Max, or Unit are missed or only partly read.
- A two-row header is merged when the second row is Min / Typ / Max. Footnotes such as `(1)` are appended to the conditions text when that note is on the same page.
- Subscripts depend on the text layer. `RDS(on)` survives when the PDF encodes it that way.
- OCR is the vendored docpipe path (Tesseract via pytesseract, English traineddata in the image). A clean scan of large text works. A photograph of a ruled table often garbles the grid even when the title block is readable. Prefer the manufacturer's text-layer PDF. Language codes must be three letters (`eng`, `eng+deu`).
- Other Tesseract languages are accepted only when that traineddata is installed. A missing language falls back to English.
- The optional LLM never replaces a value the rules already found, and it is not a check on electrical correctness.
- These JSON limits are not a substitute for the datasheet when you are choosing a part for a design.

### Legal

You may only process files you supply: an upload, a key-value record you already stored, or a direct URL you are allowed to fetch. Do not point the Actor at aggregator or mirror sites. The block list is there as a guard, not as a promise that every mirror is named.

Datasheet text and drawings are copyrighted by the manufacturer. The default output is the structured values plus a short snippet so you can find the row again. `includePageText` stores full page text and is off unless you turn it on. You are responsible for having the right to make and keep that copy.

Snippets redact email addresses and phone-like numbers. A datasheet can still contain names or other personal data. Do not publish a dataset that you are not allowed to share.

The Actor does not log in to any site and does not bypass access controls.

### Pricing events

Event name constants live in `src/settings.py`:

- `datasheet-parsed` — primary event, one per successfully parsed file (`ok` or `partial` with extracted data). **$0.02**.
- `page-ocr` — one per OCR'd page on a file that was charged. **$0.002**. A failed file is not charged for either event.

Both are charged with `Actor.charge` after the file has been parsed, using an idempotency key of the file SHA-256 (and the page index for OCR). `push_data` does not pass `charged_event_name`.

Console checklist before you publish:

1. Keep pay-per-event pricing with `datasheet-parsed` at **$0.02** and `page-ocr` at **$0.002**. Those prices are far above the measured compute for a digital datasheet. Do not also charge a failed file.
2. Remove `apify-default-dataset-item` so dataset rows are not billed a second time.
3. Keep `apify-actor-start` at the platform default if you want the free first 5 seconds. Do not also add a custom start event.

### docpipe

`docpipe/` is the document pipeline from `apify-tender-attachment-parser` at commit `8fabfe24f8845b6ae54d2d97568c3e1aa60dea88`. The only local change is in `docpipe/pdf.py`: a page with no image and almost no text is not sent to Tesseract. See `docpipe/VENDORED_FROM`. Datasheet tables, part-number choice, aggregator host checks, and snippets live in `src/`.

`scripts/sync_docpipe.sh` replaces the tree from GitHub, from `--path`, or from `--tar` (pass `--commit` for a tarball). A sync drops local edits.

### 中文摘要

Datasheet Parser 把你自己提供的电子元器件数据手册 PDF 解析成结构化规格 JSON，供硬件工程师、器件采购和 BOM/PLM 使用。输入只能是上传的文件，或制造商等站点上的直接 PDF 链接。不会抓取 AllDataSheet、Datasheet4U 等数据手册汇总站，也不会登录或绕过访问限制。

默认不输出整页原文（数据手册受版权保护），只输出参数、数值，以及不超过约 180 字的出处（文件名 + 页码）。需要全文时，必须显式打开 `includePageText`。扫描页用 Tesseract OCR。单位可换算到 SI，原始数值仍保留。单个文件失败不会中断整个运行。

计费事件：每成功解析一份文件收取 `datasheet-parsed`（$0.02），每 OCR 一页收取 `page-ocr`（$0.002）。下载或解析失败的文件不收费。请关闭合成事件 `apify-default-dataset-item`，否则每条数据集记录会被再计一次费。建议运行内存 512 MB，超时 300 秒。默认最多读 120 页；超出时记录里会有 `pagesProcessed`、`pagesTotal` 和截断警告。单次下载（含连接、TLS、重定向和重试）最多约 20 秒；平台运行时间还包含容器启动和结束，所以一次用满下载时限的运行常显示约 28–30 秒。st.com、onsemi.com 等会拦截云 IP，运行一开始就会提示改上传 PDF。不支持 Apify Proxy；可以自备代理 URL。若至少有一份文件解析成功，运行状态为 SUCCEEDED，失败项仍会列出。若全部失败或输入为空，状态为 FAILED。SUMMARY 和状态消息里的失败项带有类别（blocked、timeout、invalid_input、parse_error、other）和域名，不含完整 URL 或查询串。

# Actor input Schema

## `datasheetUrls` (type: `array`):

Direct http(s) links to PDF (or ZIP-of-PDF) files, typically the manufacturer's own file URL. Each entry is a URL string or an object with a url field. HTML catalog pages are not followed. Hosts such as AllDataSheet and Datasheet4U are rejected. st.com often times out and onsemi.com often returns HTTP 403 from cloud IPs. Upload those PDFs with Datasheet files instead of pasting the URL. Your own proxy URLs are optional; Apify Proxy is not used.

## `datasheetFiles` (type: `array`):

Upload PDF, image, or ZIP files. The file picker stores each file in a key-value store and passes the record URL. You can also pass a record key from this run's default key-value store (for example "nw3401n.pdf") when the file was already uploaded there.

## `maxFiles` (type: `integer`):

Maximum number of datasheets to parse after ZIP expansion. Extra files are skipped.

## `maxPages` (type: `integer`):

Read at most this many pages of each PDF. The default is 120, which covers a typical datasheet such as the 68-page TI LM358 at the recommended 512 MB. A longer file is still returned as partial: pagesProcessed and pagesTotal are set, and the warnings explain that the rest was not read. The maximum is 200. Lower this for a fully scanned PDF so OCR can finish inside the 300 second run timeout.

## `maxFileSizeMb` (type: `integer`):

Reject a download or upload larger than this. ZIP members are checked individually, and the archive's total uncompressed size is also capped.

## `ocrEnabled` (type: `boolean`):

Run Tesseract on pages that have almost no text layer. English traineddata is installed in the image. This is the main per-page cost.

## `ocrLanguages` (type: `string`):

Tesseract language codes, for example eng or eng+deu. Traineddata must exist in the image. eng is installed; a missing language falls back to eng.

## `includePageText` (type: `boolean`):

Off by default. Datasheet prose is copyrighted. Leave this off unless you have the right to store the full text. Specs, pinout, and short provenance snippets are always returned.

## `partNumberHint` (type: `string`):

Optional part number or ordering-code fragment. Matching codes are listed first. A hint that does not appear in the file is reported as a warning and does not replace extracted codes.

## `componentCategoryHint` (type: `string`):

auto scores the first pages. Any other value is stored as the category and the guess is still reported as detectedCategory.

## `normalizeUnits` (type: `boolean`):

Keep the original min/typ/max/unit and also write normalizedValue in SI (V, A, ohm, F, Hz, W, s, and K for temperature).

## `useLlm` (type: `boolean`):

Off by default. When on, only empty manufacturer, series, and description fields are sent, using the extracted fields rather than the full datasheet. You must supply your own API key. Nothing is sent if the key is missing.

## `llmApiKey` (type: `string`):

Your key for the OpenAI-compatible endpoint. Stored as a secret input. It is not written to the dataset.

## `llmBaseUrl` (type: `string`):

OpenAI-compatible base URL. The Actor calls POST {base}/chat/completions.

## `llmModel` (type: `string`):

Model name sent to the endpoint.

## `proxyConfiguration` (type: `object`):

Leave this empty unless a download should use your own proxy URLs. Apify Proxy is not available. If a manufacturer blocks the download, upload the PDF instead.

## Actor input object example

```json
{
  "datasheetUrls": [
    "https://www.ti.com/lit/ds/symlink/lm358.pdf"
  ],
  "maxFiles": 10,
  "maxPages": 120,
  "maxFileSizeMb": 20,
  "ocrEnabled": true,
  "ocrLanguages": "eng",
  "includePageText": false,
  "componentCategoryHint": "auto",
  "normalizeUnits": true,
  "useLlm": false,
  "llmBaseUrl": "https://api.openai.com/v1",
  "llmModel": "gpt-4o-mini",
  "proxyConfiguration": {}
}
```

# Actor output Schema

## `results` (type: `string`):

One dataset item per file, including error items. Full page text is present only when includePageText was enabled.

## `summary` (type: `string`):

How many files were parsed, which failed, and the failure category and domain of each failed URL. Categories are blocked, timeout, invalid_input, parse_error, or other. The same JSON is stored as OUTPUT and SUMMARY. A run where every input fails ends with status FAILED. A run that parsed at least one file stays SUCCEEDED and still lists the failures.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "datasheetUrls": [
        "https://www.ti.com/lit/ds/symlink/lm358.pdf"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("leonyu/datasheet-parser").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "datasheetUrls": ["https://www.ti.com/lit/ds/symlink/lm358.pdf"] }

# Run the Actor and wait for it to finish
run = client.actor("leonyu/datasheet-parser").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "datasheetUrls": [
    "https://www.ti.com/lit/ds/symlink/lm358.pdf"
  ]
}' |
apify call leonyu/datasheet-parser --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,leonyu/datasheet-parser"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/W3oB1nFxVm7Lm5cOg/builds/gGWLVcmFp7r8jAnIL/openapi.json
