# Image Alt Audit (`zerobreak/image-alt-audit`) Actor

Image alt text auditor that crawls any webpage and flags images with missing, empty, or inadequate alt attributes, so SEO teams and accessibility auditors can fix issues before they affect rankings or compliance.

- **URL**: https://apify.com/zerobreak/image-alt-audit.md
- **Developed by:** [ZeroBreak](https://apify.com/zerobreak) (community)
- **Categories:** SEO tools
- **Features:** Limited permissions
- **Stats:** 2 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.99 / 1,000 results

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

## Image Alt Audit: Find and Fix Missing Alt Text on Any Website

Image alt text is one of the most commonly skipped SEO and accessibility fixes on the web. This actor scans any webpage, reads every `img` tag, and tells you exactly which images have missing, empty, or too-short alt attributes. Paste in a single URL or a whole list and get a row-by-row breakdown in seconds.

### What data does this actor extract?

Each row in the output dataset covers one image on one page. You get the page URL, the image URL, the exact alt text (or nothing if it is absent), a status flag, and the raw HTML tag for context.

| Field | Type | Description |
|-------|------|-------------|
| `pageUrl` | string | URL of the audited page |
| `imageUrl` | string | src attribute of the image |
| `altText` | string | Alt attribute value (empty string if blank or missing) |
| `altStatus` | string | `missing`, `empty`, `short`, or `ok` |
| `altLength` | integer | Character count of the alt text |
| `isDecorative` | boolean | True when `alt=""` marks a decorative image (WCAG H67) |
| `htmlTag` | string | Full HTML of the img element |
| `pageTitle` | string | Page title, for quick identification |
| `scrapedAt` | string | ISO 8601 timestamp |

#### What the status codes mean

- **missing**: The `img` tag has no `alt` attribute at all. Search engines and screen readers get nothing.
- **empty**: `alt=""` is present. This is correct for purely decorative images (WCAG H67), so the `isDecorative` field is set to `true`.
- **short**: Alt text exists but is under the configured minimum length (default 10 characters). Catches placeholders like `"img"` or `"photo"`.
- **ok**: Alt text meets the length threshold. Only included in output when `includeOkImages` is `true`.

### Use cases

- **SEO auditing**: find images with no alt text dragging down your search rankings without clicking through every page manually
- **Accessibility compliance**: check pages against WCAG 2.1 image text alternatives before a compliance review
- **Content inventory**: get a full image inventory across multiple pages by enabling `includeOkImages`
- **Pre-launch QA**: validate image alt coverage before pushing a new site or redesign live
- **Ongoing monitoring**: run on a schedule and pipe results into Google Sheets or Slack to catch regressions

### Input

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `url` | string | required | Single page URL to audit |
| `urls` | array | \[] | Additional URLs to audit (one per line) |
| `maxUrls` | integer | 100 | Maximum pages to process per run |
| `minAltLength` | integer | 10 | Alt text shorter than this is flagged as `short` |
| `includeOkImages` | boolean | false | Include images with adequate alt text in output |
| `timeoutSecs` | integer | 300 | Total actor timeout in seconds |
| `requestTimeoutSecs` | integer | 30 | Per-request timeout in seconds |
| `proxyConfiguration` | object | Datacenter (Anywhere) | Proxy type and location for requests. Supports Datacenter, Residential, Special, and custom proxies. Optional. |

#### Example input

```json
{
    "url": "https://apify.com",
    "urls": ["https://apify.com/about", "https://apify.com/pricing"],
    "maxUrls": 50,
    "minAltLength": 10,
    "includeOkImages": false,
    "proxyConfiguration": { "useApifyProxy": true }
}
```

### How it works

1. Collects all URLs from `url` and `urls`, deduplicates them, and applies the `maxUrls` cap
2. Fetches each page with a realistic browser User-Agent header, following redirects
3. Parses every `img` element in the HTML using BeautifulSoup
4. Classifies each image as `missing`, `empty`, `short`, or `ok` based on its `alt` attribute
5. Pushes results to the Apify dataset (skipping `ok` images unless `includeOkImages` is enabled)

### Integrations

Connect Image Alt Audit with other apps using [Apify integrations](https://apify.com/integrations). You can send results directly to Google Sheets, trigger Slack notifications when issues are found, or connect via Make or Zapier to fit into any existing workflow. Use [webhooks](https://docs.apify.com/integrations/webhooks) to trigger downstream actions the moment a run finishes.

### FAQ

**How many pages can it process per run?**
Up to 1000, controlled by `maxUrls`. The default is 100 to keep costs predictable. For large sites, run multiple smaller batches.

**Does it crawl the whole site or just the pages I give it?**
It audits only the URLs you provide. It does not follow links or crawl child pages automatically.

**Why is `alt=""` flagged as decorative and not a problem?**
An empty alt string is the correct way to mark decorative images per WCAG 2.1 technique H67. Screen readers skip them, which is the intended behavior. The actor records them with `isDecorative: true` so you can verify they really are decorative.

**Can it handle JavaScript-rendered pages?**
No. This actor fetches raw HTML. Images loaded by JavaScript after page render will not appear. For JS-heavy sites, a Playwright-based actor would be needed.

**What counts as a "short" alt text?**
Anything under `minAltLength` characters (default 10). This catches common placeholder values like `"image"`, `"photo"`, or `"img1"` that technically have an alt attribute but add no meaningful context.

### Start finding missing alt text today

Drop in a URL and run it. The first run takes under a minute on most pages. Results go straight into your Apify dataset, ready to export or pipe into any tool you already use for SEO or accessibility work.

# Actor input Schema

## `url` (type: `string`):

Single URL to audit for image alt text. Add multiple URLs using the 'urls' field below.

## `urls` (type: `array`):

List of URLs to audit. Enter one URL per line. Combined with the single URL above.

## `maxUrls` (type: `integer`):

Maximum number of pages to process per run. Prevents runaway costs on large lists.

## `minAltLength` (type: `integer`):

Alt text shorter than this character count is flagged as 'short'. Useful for catching placeholder alt tags like 'img' or 'x'. Logo images are exempt regardless of this setting.

## `includeOkImages` (type: `boolean`):

When enabled, also outputs images whose alt text is fine. Useful for a full inventory of all images on a page.

## `timeoutSecs` (type: `integer`):

Maximum total run time in seconds. The actor stops after this limit even if not all URLs are processed.

## `requestTimeoutSecs` (type: `integer`):

Timeout per individual HTTP request. Increase this for slow websites.

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

Select proxies to use for requests. Helps avoid IP blocking and rate limits. Datacenter proxies are fastest; Residential proxies are harder to detect.

## Actor input object example

```json
{
  "url": "https://apify.com",
  "urls": [
    "https://apify.com",
    "https://apify.com/about"
  ],
  "maxUrls": 100,
  "minAltLength": 4,
  "includeOkImages": false,
  "timeoutSecs": 300,
  "requestTimeoutSecs": 30,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# 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 = {
    "url": "https://apify.com",
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("zerobreak/image-alt-audit").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 = {
    "url": "https://apify.com",
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("zerobreak/image-alt-audit").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 '{
  "url": "https://apify.com",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call zerobreak/image-alt-audit --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,zerobreak/image-alt-audit"
        }
    }
}
```

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/Y8iSSlaNxcJPGWGM4/builds/T4Hw045N2eoxN18yv/openapi.json
