# WP-CLI Command to Scan Content for Accessibility Problems

> Adds a "wp a11y-scan" command that checks published posts and pages for images without alt text, empty links, iframes without titles, positive tabindex and skipped heading levels, and prints a table you can export.

- Type: PHP
- Runs: Run everywhere
- Category: [Accessibility](https://wpide.com/library/category/accessibility/)
- Tags: wp-cli, audit, content
- Author: WPIDE Team
- Installs: 0
- Updated: 2026-10-28
- Page: https://wpide.com/library/a11y-wp-cli-content-scan/

## Code

```php
if ( defined( 'WP_CLI' ) && WP_CLI && class_exists( 'WP_HTML_Tag_Processor' ) ) {
    WP_CLI::add_command( 'a11y-scan', function ( $args, $assoc ) {
        $type   = isset( $assoc['post_type'] ) ? sanitize_key( $assoc['post_type'] ) : 'post,page';
        $format = isset( $assoc['format'] ) ? $assoc['format'] : 'table';
        $rows   = array();
        $paged  = 1;

        do {
            $posts = get_posts( array(
                'post_type'      => explode( ',', $type ),
                'post_status'    => 'publish',
                'posts_per_page' => 100,
                'paged'          => $paged++,
                'orderby'        => 'ID',
                'order'          => 'ASC',
            ) );

            foreach ( $posts as $post ) {
                $issues = array();
                $tags   = new WP_HTML_Tag_Processor( $post->post_content );
                $level  = 1;
                while ( $tags->next_tag() ) {
                    $tag = $tags->get_tag();
                    if ( 'IMG' === $tag && null === $tags->get_attribute( 'alt' ) ) {
                        $issues['img'] = 'image without alt';
                    } elseif ( 'IFRAME' === $tag && ! $tags->get_attribute( 'title' ) ) {
                        $issues['iframe'] = 'iframe without title';
                    } elseif ( preg_match( '/^H([1-6])$/', (string) $tag, $m ) ) {
                        if ( (int) $m[1] > $level + 1 ) {
                            $issues['heading'] = 'skipped heading level';
                        }
                        $level = (int) $m[1];
                    }
                    if ( (int) $tags->get_attribute( 'tabindex' ) > 0 ) {
                        $issues['tabindex'] = 'positive tabindex';
                    }
                }
                if ( preg_match( '#<a\b[^>]*>\s*</a>#i', $post->post_content ) ) {
                    $issues['link'] = 'empty link';
                }
                if ( $issues ) {
                    $rows[] = array( 'ID' => $post->ID, 'type' => $post->post_type, 'title' => $post->post_title, 'issues' => implode( '; ', $issues ), 'url' => get_permalink( $post ) );
                }
            }
        } while ( count( $posts ) === 100 );

        if ( ! $rows ) {
            WP_CLI::success( 'No problems found.' );
            return;
        }

        WP_CLI\Utils\format_items( $format, $rows, array( 'ID', 'type', 'title', 'issues', 'url' ) );
    }, array( 'shortdesc' => 'Scan published content for common accessibility problems.' ) );
}
```

## Notes

Run "wp a11y-scan --post_type=page --format=csv > report.csv"; it reads posts in batches so it works on large sites.

## How to use it

Install the free WPIDE plugin (https://wordpress.org/plugins/wpide/), find "WP-CLI Command to Scan Content for Accessibility Problems" in its snippet library and add it in one click; or create a new PHP snippet in WPIDE (or any code snippets plugin) and paste the code above. More snippets: https://wpide.com/library/
