# PDF & Office Document Accessibility Auditor - DocA11y (`leons0016/document-accessibility-auditor`) Actor

PDF & Office document accessibility auditor: crawl a website, list every PDF, Word, PowerPoint and Excel file, run PDF/UA and WCAG 2.1 machine checks.

- **URL**: https://apify.com/leons0016/document-accessibility-auditor.md
- **Developed by:** [Leon s](https://apify.com/leons0016) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $16.00 / 1,000 document auditeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## PDF & Office Document Accessibility Auditor - DocA11y

**DocA11y is a PDF and Office document accessibility auditor for whole websites.** It crawls a site, lists every PDF, Word (.docx), PowerPoint (.pptx) and Excel (.xlsx) file it finds, and runs machine checks on each one: veraPDF PDF/UA-1 validation plus its own structure checks for PDFs, and accessibility checks for Office files. Every failed check is mapped to a WCAG 2.1 success criterion, with a severity and a plain-English fix hint. Documents posted after your compliance date are flagged first, and re-runs audit only new or changed files.

Published by LeonS. Support: atulhritik@hotmail.com.

### Use cases

- **US state and local government web teams** that must work through PDF, Word, PowerPoint and Excel files before an ADA Title II deadline. The Department of Justice's April 2026 interim final rule moved the web accessibility dates to 26 April 2027 (public entities serving 50,000 people or more) and 26 April 2028 (smaller entities and special districts), as reported in published summaries. Read the rule text and set your own date in the input.
- **Accessibility consultancies and web agencies** that need a document inventory and a prioritised fix list for many client sites.
- **Organisations under the European Accessibility Act, UK public bodies and Indian government sites** that want a repeatable PDF accessibility checker for their document libraries.
- **Content teams** that want a scheduled check so that newly uploaded PDFs and Office files are tested the month they appear.

### What you get

- A whole-site document inventory: URL, linking pages (up to 5), size, Last-Modified, file creation and modification dates, page count, title and language.
- PDF checks: veraPDF PDF/UA-1 machine validation plus 14 structure checks (tagged or not, scanned pages, language, title, figure alt text, table headers, headings, bookmarks, tab order, link text, form labels, font Unicode maps, encryption).
- Office checks: 8 for Word, 6 for PowerPoint and 5 for Excel (alt text, headings, table headers, titles, language, link text, slide titles, sheet names and more).
- A WCAG 2.1 success criterion, severity (critical, serious, moderate, minor) and fix hint for every issue.
- A scope label (`in-scope`, `likely-exception`, `review`) and a priority score from 0 to 95 for each document.
- Diff mode: documents whose ETag, Last-Modified and size, or whose content hash, did not change are not audited again.
- Outputs: dataset views, an HTML `REPORT`, `INVENTORY.csv` (opens in Excel), a JSON `OUTPUT`, and optional webhook and Slack messages.

### How to use

1. Open the Actor and press **Start** with the prefilled input to see the output format. The prefill is a self-test: mode **Audit these document URLs** with five small, synthetic sample files (two PDFs, two Word files and one Excel file, some with deliberate accessibility problems) that the publisher hosts in its public repository (`github.com/leons0016/ADApps`, folder `samples/doca11y`). No third-party website is contacted. It costs one audit run fee plus five document audits.
2. For your own site, switch **Mode** to **Crawl a website**, clear the sample links, enter your site as a **Start URL** (usually the home page), and set **Max HTML pages** and **Compliance date**.
3. Open the **Output** tab: the `Documents` view, the `REPORT` record (top 50 documents to fix first) and `INVENTORY.csv`.
4. Save the settings as a **Task**. Scheduling needs one finished run of the Actor first.
5. Add a **Schedule** to the task, for example monthly: cron `0 3 1 * *` with your time zone. New schedules start disabled, so enable it. Set the task timeout to 0 or to several hours for large sites.

### Input

| Field | What it does | Default |
|---|---|---|
| `mode` | `crawl` (find documents) or `urls` (audit only the document URLs you give) | `crawl` (prefill `urls`) |
| `startUrls` | Where the crawl starts (up to 50; 1 on the Apify free plan) | none (no prefill) |
| `documentUrls` | Up to 5,000 document links for mode `urls` | empty (prefill: the five sample files) |
| `useSitemap` | Also read `/sitemap.xml` and sitemaps named in robots.txt | true |
| `documentTypes` | `pdf`, `docx`, `pptx`, `xlsx` | all four |
| `maxPages` | HTML pages to fetch, 1 to 100,000 | 1,000 (prefill 30) |
| `maxDepth` | Link depth, 0 to 20 | 6 |
| `maxDocuments` | Documents to audit per run, 1 to 20,000 | 2,000 (prefill 10) |
| `includeGlobs`, `excludeGlobs` | URL patterns to follow or never fetch (`*` and `**` match any characters) | exclude `**/calendar/**`, `**?print=*` |
| `allowedDomains` | Extra hosts (a CDN) from which documents, not pages, are fetched | empty |
| `maxDocumentSizeMb` | Larger files are listed, not audited, not charged. 1 to 500 | 50 |
| `respectRobotsTxt`, `iAmAuthorised` | robots.txt is respected by default. Switching it off needs the permission box | true / false |
| `complianceDate` | `YYYY-MM-DD` used for the scope label | 2027-04-26 |
| `archivePathHints` | URL parts that hold archived content | `/archive`, `/archives`, `/minutes/20`, `/agenda-archive` |
| `onlyNewOrChanged` | Audit only new or changed documents (uses the task history) | true |
| `maxResultsPerRun` | Stop after this many document results | 5,000 |
| `webhookUrl`, `slackWebhookUrl` | Optional notifications (the Slack URL is stored as a secret) | empty |
| `includePassedDocuments` | Also push items for documents with 0 failed checks | true |
| `stateKey`, `perDocumentTimeoutSecs`, `maxConcurrency`, `userAgentSuffix`, `debugKeepRaw` | Advanced options | see the input form |

Sample input:

```json
{
  "mode": "crawl",
  "startUrls": [{ "url": "https://www.cityofexample.gov/" }],
  "maxPages": 5000,
  "maxDocuments": 2000,
  "complianceDate": "2027-04-26",
  "onlyNewOrChanged": true
}
```

Input is validated before anything is charged. A wrong value stops the run with a message and no charge.

### Output

Each document is one dataset item (the `Documents` view). Abridged example with invented data:

```json
{
  "recordType": "document",
  "url": "https://www.cityofexample.gov/files/budget-2027.pdf",
  "docType": "pdf",
  "status": "audited",
  "title": "Budget 2027",
  "language": "en-US",
  "pages": 12,
  "tagged": true,
  "postedDate": "2027-06-01",
  "postedDateSource": "file-modified",
  "verapdfCompliant": false,
  "failedChecks": 2,
  "topIssues": ["Figures without alt text", "Tables without headers"],
  "issues": [
    { "checkId": "PDF-ALT", "source": "structure", "wcag": ["1.1.1"], "level": "A", "severity": "serious", "count": 3, "pages": [2, 5],
      "message": "Figure elements have no alternative text.",
      "fix": "Add alternative text to each meaningful figure, or mark purely decorative images as artifacts." }
  ],
  "scope": "in-scope",
  "scopeReasons": ["posted-after-compliance-date"],
  "priority": 62,
  "disclaimer": "Automated checks find many but not all accessibility problems. ..."
}
```

- **Documents view**: priority, scope, type, title, URL, failed checks, pages, posted date, tagged, language, top issues, found on.
- **Issues view**: one row per issue (check ID, WCAG criterion, severity, count, message, fix hint, page numbers).
- **Run summary view**: the last item of every run, with pages crawled, documents found, audited, unchanged, removed, failed downloads, in-scope count, counts per WCAG criterion and the stop reason.
- Statuses: `audited`, `encrypted` (needs a password, so only the encryption issue is reported), `unchanged`, `legacy-format` (.doc, .ppt, .xls are listed, not audited), `too-large`, `download-failed`, `not-parsable`, `skipped-cap`.
- **Key-value store**: `OUTPUT` (summary and top 50), `REPORT` (HTML), `INVENTORY.csv` (UTF-8 with byte-order mark) and, with `debugKeepRaw`, `VERAPDF-<hash>` records.

No document text is stored. Results contain URLs, metadata, hashes, counts, page numbers and generic messages only. Downloaded files are deleted after each audit.

How the numbers work: `failedChecks` is the number of distinct failed checks. The priority score is 40 for `in-scope` or 15 for `review`, plus 25 if any critical issue, plus up to 10 for serious issues (3 or more give the full 10), plus 10 if the document is linked from a start page, plus 5 for a service word such as application or permit in the URL or title, plus up to 5 for length (50 pages or more give 5). The weights add up to 95. A document with no failed checks scores 0.

### Pricing

DocA11y uses Apify pay-per-event pricing. You pay only for these events:

| Event | When it is charged | Price (Bronze) |
|---|---|---|
| Audit run (`watch-check`) | Once per run, after the input is valid | $0.10 |
| HTML page crawled (`page-crawled`) | Per HTML page fetched in crawl mode | $0.0005 |
| Document audited (`document-audited`) | Per new or changed document audited (status `audited` or `encrypted`); one event per 100 pages started, so a 250-page PDF is 3 events | $0.02 |
| Unchanged document confirmed (`document-rechecked`) | Per unchanged document confirmed by a HEAD request or an unchanged content hash | $0.0005 |

Silver plan prices are 10% lower and Gold plan prices 20% lower. Apify also adds its own automatic start event ($0.00005 per GB of run memory; 2 GB by default, so $0.0001 per run), which is not included in the examples. Not charged: files that are too large, failed downloads, files that cannot be parsed, legacy formats and the run-summary item. You can set a maximum cost per run in Apify; the run stops cleanly at the limit and the next run continues where it stopped.

**Monthly cost** = runs x `watch-check` + pages x `page-crawled` + new or changed documents x `document-audited` + unchanged documents x `document-rechecked`.

| Example | Calculation (Bronze prices) | Cost |
|---|---|---|
| Small town, monthly run: 1,500 pages, 30 new or changed, 400 unchanged | 0.10 + 0.75 + 0.60 + 0.20 | $1.65 |
| County site, weekly (4.33 runs a month): 6,000 pages per run, 120 new or changed a month, 2,500 unchanged per run | 0.433 + 12.99 + 2.40 + 5.4125 | about $21.24 |
| Agency, 20 client sites monthly: 60,000 pages, 900 new or changed, 15,000 unchanged in total | 2.00 + 30.00 + 18.00 + 7.50 | $57.50 |
| First full audit of a county site: 6,000 pages, 2,500 documents | 0.10 + 3.00 + 50.00 | $53.10 once |

**Free plan**: crawls at most 100 pages, audits at most 10 documents and uses 1 start URL per run. When a limit applies, the run ends successfully, the run summary says which limit was used, and the status message reads: "Free plan: crawled N pages and audited D of F documents found. Upgrade your Apify plan for full audits."

### Notifications

Open the Actor's **Integrations** tab and add Slack, email, Google Drive, Zapier, Make, n8n or a webhook on `ACTOR.RUN.SUCCEEDED`, and a second one on `ACTOR.RUN.FAILED`. Example Slack message template:

```
DocA11y finished: {{resource.status}}. Open the report: https://api.apify.com/v2/key-value-stores/{{resource.defaultKeyValueStoreId}}/records/REPORT
```

You can also set `webhookUrl` (the `OUTPUT` JSON is posted) or `slackWebhookUrl` in the input.

### Compliance note and limitations

Automated checks find many but not all accessibility problems. They cannot certify WCAG 2.1 AA or PDF/UA conformance. Manual review is required. Scope labels are hints based on dates and paths, not legal advice. The ADA Title II exceptions (archived web content, pre-existing documents not used to access services, third-party content, individualized documents) need human review.

- Pages that need JavaScript to show their links are not crawled. Use the sitemap or the URL list mode.
- No logins, forms, CAPTCHAs or password-protected areas. Password-protected PDFs are reported as `encrypted`.
- The posted date is an estimate: file metadata first, then HTTP Last-Modified, then sitemap `lastmod`, then the date the document was first seen.
- A document that is linked under several URLs is audited once; the other URLs are listed as aliases in `INVENTORY.csv`.
- Conditional page fetches are not used, because a "not modified" answer carries no links. Unchanged pages are fetched again and charged as pages; unchanged documents are cheap.
- Redirects that leave the audited site are not followed into results, but the request to the redirect target is made.
- Documents are checked as downloaded; on very large files the time limit per document applies.

**robots.txt**: respected by default. You can switch it off only for your own site, or one you have permission to audit, with the permission box. Even then there is no login, no form submission, and at least 0.5 seconds between requests to one host. You are responsible for the crawl.

### FAQ

**Does DocA11y make my documents compliant?** No. It reports machine-checkable problems and fix hints. It cannot certify conformance and it does not repair files.

**Which PDF standard does it check?** PDF/UA-1 (ISO 14289-1) through veraPDF, plus its own structure checks. PDF/UA-2 and WTPDF are planned for a later version.

**What do the three scope labels mean?** `in-scope`: posted on or after your compliance date. `likely-exception`: older, or on an archive path. `review`: older but possibly used to apply for or access a service, or the posted date is unknown.

**How does a re-run stay cheap?** The task remembers each document. Documents with the same ETag, or the same Last-Modified and size, or the same content hash, are confirmed unchanged and charged only the small recheck event.

**How do I forget the history?** Delete the named key-value store `leons-doca11y-state` in your account. The next run audits everything again.

**Why was a document not audited?** See its `status`: too large (raise `maxDocumentSizeMb`), failed download (retried next run), not parsable (corrupt or time limit), legacy format, or skipped because of the document limit.

**Does it store my documents?** No. Files are deleted after the audit and results contain no document text.

**Can it check HTML pages?** No. It audits documents. A headless-browser Actor would be needed for HTML pages.

**Are there other Actors by the same publisher?** See the publisher page on Apify.

### Credits and licences

PDF/UA validation is done by [veraPDF](https://verapdf.org), used as an unmodified separate program under the Mozilla Public License 2.0 (veraPDF is dual-licensed MPL-2.0+ and GPL-3.0+). Other components: Crawlee for Python, pikepdf (MPL-2.0), pdfplumber, python-docx, python-pptx and openpyxl.

### Changelog and support

See the Changelog in the Information tab. Questions and bug reports: open an issue on the Actor's Issues tab or write to atulhritik@hotmail.com.
Privacy policy: https://raw.githubusercontent.com/leons0016/ADApps/main/privacy/P2-DocA11yCrawler.txt

Third-party licences and attributions: see `docs/THIRD_PARTY_NOTICES.txt` in the Actor source.

# Changelog

This Actor's version history is a separate document: https://apify.com/leons0016/document-accessibility-auditor/changelog.md

# Actor input Schema

## `mode` (type: `string`):

Crawl finds documents for you. URL list audits only the files you give. The prefill uses the URL list with five sample files. Example: crawl.

## `startUrls` (type: `array`):

Pages where the crawl starts, usually your home page. Example: https://www.cityofexample.gov/. Up to 50 (1 on the Apify free plan).

## `documentUrls` (type: `array`):

Mode 'Audit these document URLs' only. One link per line, up to 5,000. The prefill is five synthetic sample files hosted by the publisher for a self-test. Example: https://www.cityofexample.gov/files/budget-2027.pdf.

## `useSitemap` (type: `boolean`):

Also reads /sitemap.xml and the sitemaps listed in robots.txt. Sitemap pages count towards the page limit.

## `documentTypes` (type: `array`):

File types to audit. Old .doc, .ppt and .xls files are always listed as legacy formats but never audited. Example: pdf and docx.

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

Pages fetched to find documents. Example: 1000. The Apify free plan crawls at most 100.

## `maxDepth` (type: `integer`):

How many links away from a start URL the crawl may go. 0 means start pages only. Example: 6.

## `maxDocuments` (type: `integer`):

Stops auditing after this many documents in one run. Example: 2000. The Apify free plan audits at most 10.

## `includeGlobs` (type: `array`):

If not empty, only pages whose URL matches are followed. \* and \*\* match any characters. Example: https://www.example.gov/departments/\*\*.

## `excludeGlobs` (type: `array`):

Pages and documents whose URL matches are never fetched. Example: **/calendar/** keeps the crawl out of endless calendar pages.

## `allowedDomains` (type: `array`):

Other host names that may hold your documents, such as a CDN. Pages on these hosts are not crawled; only documents are fetched. Example: docs.example.gov.

## `maxDocumentSizeMb` (type: `integer`):

Larger files are listed but not audited and not charged. Example: 50.

## `respectRobotsTxt` (type: `boolean`):

Recommended. Switching this off needs the permission box below.

## `iAmAuthorised` (type: `boolean`):

Required to switch off robots.txt. You are responsible for the crawl. The delay between requests to one host stays at 0.5 seconds or more.

## `complianceDate` (type: `string`):

Your accessibility deadline as YYYY-MM-DD. Example: 2027-04-26 (ADA Title II, 50,000 or more people) or 2028-04-26 (smaller entities), as published at the time of writing.

## `archivePathHints` (type: `array`):

URL path parts that hold archived content, which may fall under an exception. Example: /archive.

## `standard` (type: `string`):

The PDF/UA profile that veraPDF checks. PDF/UA-2 and WTPDF are planned for a later version.

## `onlyNewOrChanged` (type: `boolean`):

Uses the history of this task, so schedules only pay for what changed. Turn off to audit everything again (charged).

## `maxResultsPerRun` (type: `integer`):

Stops auditing after this many document results. The rest is audited in the next run. Example: 5000.

## `webhookUrl` (type: `string`):

Optional. The run summary (OUTPUT) is posted here as JSON when the run ends. Example: https://hooks.example.com/doca11y.

## `slackWebhookUrl` (type: `string`):

Optional. A short Slack message with the top documents is posted when the run ends.

## `includePassedDocuments` (type: `boolean`):

Push an item for documents with 0 failed checks too. They are charged either way, because the audit was done.

## `stateKey` (type: `string`):

Share the audit history between tasks or keep it apart. Letters, digits, dot, dash, underscore. Example: city-website.

## `perDocumentTimeoutSecs` (type: `integer`):

A document that takes longer is reported as not parsable and is not charged. Example: 120.

## `maxConcurrency` (type: `integer`):

How many pages and documents are handled at the same time. Lower it for slow sites. Example: 4.

## `userAgentSuffix` (type: `string`):

Optional text added to the User-Agent so that site owners can recognise your audit. Example: audit-for-city-it.

## `debugKeepRaw` (type: `boolean`):

Saves the raw veraPDF JSON of failed PDFs as VERAPDF-<hash> records in the key-value store, for support and debugging.

## Actor input object example

```json
{
  "mode": "urls",
  "documentUrls": [
    "https://raw.githubusercontent.com/leons0016/ADApps/main/samples/doca11y/annual-report.pdf",
    "https://raw.githubusercontent.com/leons0016/ADApps/main/samples/doca11y/untagged-policy.pdf",
    "https://raw.githubusercontent.com/leons0016/ADApps/main/samples/doca11y/handbook-good.docx",
    "https://raw.githubusercontent.com/leons0016/ADApps/main/samples/doca11y/handbook-bad.docx",
    "https://raw.githubusercontent.com/leons0016/ADApps/main/samples/doca11y/park-permits.xlsx"
  ],
  "useSitemap": true,
  "documentTypes": [
    "pdf",
    "docx",
    "pptx",
    "xlsx"
  ],
  "maxPages": 30,
  "maxDepth": 6,
  "maxDocuments": 10,
  "includeGlobs": [],
  "excludeGlobs": [
    "**/calendar/**",
    "**?print=*"
  ],
  "allowedDomains": [],
  "maxDocumentSizeMb": 50,
  "respectRobotsTxt": true,
  "iAmAuthorised": false,
  "complianceDate": "2027-04-26",
  "archivePathHints": [
    "/archive",
    "/archives",
    "/minutes/20",
    "/agenda-archive"
  ],
  "standard": "ua1",
  "onlyNewOrChanged": true,
  "maxResultsPerRun": 5000,
  "includePassedDocuments": true,
  "perDocumentTimeoutSecs": 120,
  "maxConcurrency": 4,
  "debugKeepRaw": false
}
```

# Actor output Schema

## `documents` (type: `string`):

Audited documents and the run summary.

## `report` (type: `string`):

Top 50 documents to fix first and failures by WCAG criterion.

## `inventory` (type: `string`):

Every document found, audited or not.

# 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 = {
    "mode": "urls",
    "documentUrls": [
        "https://raw.githubusercontent.com/leons0016/ADApps/main/samples/doca11y/annual-report.pdf",
        "https://raw.githubusercontent.com/leons0016/ADApps/main/samples/doca11y/untagged-policy.pdf",
        "https://raw.githubusercontent.com/leons0016/ADApps/main/samples/doca11y/handbook-good.docx",
        "https://raw.githubusercontent.com/leons0016/ADApps/main/samples/doca11y/handbook-bad.docx",
        "https://raw.githubusercontent.com/leons0016/ADApps/main/samples/doca11y/park-permits.xlsx"
    ],
    "maxPages": 30,
    "maxDocuments": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("leons0016/document-accessibility-auditor").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 = {
    "mode": "urls",
    "documentUrls": [
        "https://raw.githubusercontent.com/leons0016/ADApps/main/samples/doca11y/annual-report.pdf",
        "https://raw.githubusercontent.com/leons0016/ADApps/main/samples/doca11y/untagged-policy.pdf",
        "https://raw.githubusercontent.com/leons0016/ADApps/main/samples/doca11y/handbook-good.docx",
        "https://raw.githubusercontent.com/leons0016/ADApps/main/samples/doca11y/handbook-bad.docx",
        "https://raw.githubusercontent.com/leons0016/ADApps/main/samples/doca11y/park-permits.xlsx",
    ],
    "maxPages": 30,
    "maxDocuments": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("leons0016/document-accessibility-auditor").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 '{
  "mode": "urls",
  "documentUrls": [
    "https://raw.githubusercontent.com/leons0016/ADApps/main/samples/doca11y/annual-report.pdf",
    "https://raw.githubusercontent.com/leons0016/ADApps/main/samples/doca11y/untagged-policy.pdf",
    "https://raw.githubusercontent.com/leons0016/ADApps/main/samples/doca11y/handbook-good.docx",
    "https://raw.githubusercontent.com/leons0016/ADApps/main/samples/doca11y/handbook-bad.docx",
    "https://raw.githubusercontent.com/leons0016/ADApps/main/samples/doca11y/park-permits.xlsx"
  ],
  "maxPages": 30,
  "maxDocuments": 10
}' |
apify call leons0016/document-accessibility-auditor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,leons0016/document-accessibility-auditor"
        }
    }
}
```

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/nwneRbjuQIEHpPbnI/builds/5TeNQj8gNLDE9vYXB/openapi.json
