WordPress attachment pages are a leftover from the pre-block-editor era, when every uploaded media file got its own URL and a template that rendered a single image or document. For a small-to-mid publishing team running its own production install, those attachment URLs are now a quiet source of crawl waste, soft-404 ambiguity, and index bloat. The core behavior is not a bug in the traditional sense: WordPress resolves an attachment URL through the attachment rewrite rules, queries the post_type=attachment post, and only falls back to a 404 when the attachment post itself is missing or the rewrite does not match. The confusion for crawlers comes from the gap between what WordPress considers a valid resource and what a search engine considers a useful landing page.
This article walks through the exact request path, the database rows involved, the HTTP status behavior, and the failure modes that show up in crawl logs. It is written for teams that maintain their own WordPress installs and want reproducible evidence before changing template behavior, redirect rules, or sitemap output.

What an Attachment Page Actually Is in Core
When you upload an image through the media library, WordPress creates a post of type attachment in the wp_posts table. The attachment post has a post_parent pointing to the post or page where the file was first uploaded, a post_mime_type such as image/jpeg, and a guid that contains the raw file URL. The attachment post also gets a post_name derived from the filename, which becomes the slug for the attachment page.
You can confirm this with a direct SQL query:
SELECT ID, post_title, post_name, post_parent, post_mime_type, guid
FROM wp_posts
WHERE post_type = 'attachment'
AND post_mime_type LIKE 'image/%'
ORDER BY ID DESC
LIMIT 10;
The attachment page URL is then built from the parent post permalink plus the attachment slug. For a parent post at /2024/09/editorial-workflow-notes/ and an attachment named newsroom-dashboard.png, the attachment URL becomes /2024/09/editorial-workflow-notes/newsroom-dashboard/. That URL is not a redirect to the file. It is a full WordPress page request that loads the attachment.php template if your theme has one, or falls back to single.php or index.php.
The Rewrite and Query Path
WordPress matches the attachment URL through the attachment rewrite rule generated by WP_Rewrite. The rule captures the parent path and the attachment slug, then passes them to index.php?attachment=$matches[1]. The main query then looks for a post of type attachment with that slug. If the attachment post exists, WordPress returns a 200 OK status and renders the template. If the attachment post does not exist, WordPress returns a 404 Not Found status through the normal WP_Query no-results path.
This is the first point of confusion for crawlers: a URL can return 200 OK even when the parent post is unpublished, trashed, or deleted. The attachment post remains in the database unless you explicitly delete the media item. A crawler that follows an old attachment URL from a sitemap, an RSS feed, or an external link can land on a page that shows only an image and a minimal title, with no editorial context and no clear navigation back to the parent article.
Why Crawlers Treat Attachment Pages as Soft 404s
Search engines do not rely only on the HTTP status code. They also evaluate whether a page provides substantive content that matches the query intent. An attachment page for a single image often contains no meaningful text beyond the image title, caption, and description fields. Many themes render the image at full size, add a comment form, and link back to the parent post. That is a thin page by any reasonable standard.
Google’s documentation on soft 404s describes the pattern: a page returns 200 OK but the content is so thin or irrelevant that the crawler treats it as a missing page. Attachment pages are a textbook case. The crawler wastes budget on URLs that will never rank, and the site accumulates index bloat that dilutes the signal from real editorial pages.
You can see the scale of the problem with a simple count:
SELECT COUNT(*) AS attachment_count
FROM wp_posts
WHERE post_type = 'attachment'
AND post_status = 'inherit';
On a site with five years of editorial images, that number can easily exceed the number of published articles. Each attachment URL is a potential crawl target unless you actively block or redirect it.

The post_status=inherit Detail
Attachment posts use the inherit post status, not publish. That status means the attachment inherits the status of its parent post. If the parent post is published, the attachment is publicly queryable. If the parent post is trashed, the attachment is not publicly queryable through the normal query, but the attachment post still exists in the database. This inheritance is what makes attachment URLs behave inconsistently after editorial changes.
For example, if you trash a parent post, the attachment URL may start returning a 404 because the parent is no longer available. If you restore the parent, the attachment URL returns 200 again. Crawlers that saw the 404 may not revisit the URL for a long time, and crawlers that saw the 200 before the trash may keep the stale URL in their index.
Reproducing the 404 and 200 Behavior
The fastest way to see the behavior is with WP-CLI and curl. First, find an attachment URL:
wp post list --post_type=attachment --post_mime_type=image/jpeg --format=ids --posts_per_page=1
Then request the URL with headers:
curl -I https://example.com/path-to-parent/attachment-slug/
You will see HTTP/2 200 for a valid attachment page. Now delete the attachment post directly in the database or through the media library, and request the same URL again. You will see HTTP/2 404. The difference is entirely in the wp_posts row, not in the file on disk. The actual image file can still exist in wp-content/uploads/ and be served correctly at its direct file URL, while the attachment page returns 404.
This split between the file URL and the attachment page URL is another source of crawler confusion. A crawler can fetch /wp-content/uploads/2024/09/newsroom-dashboard.png and get a 200 with the image bytes, then fetch /2024/09/editorial-workflow-notes/newsroom-dashboard/ and get a 404. The crawler has no reliable way to know that the two URLs are related unless the site provides a canonical or redirect signal.
What the Database Schema Tells You
The wp_posts table stores the attachment post, but the file metadata lives in wp_postmeta. The _wp_attached_file meta key holds the relative path to the uploaded file, and _wp_attachment_metadata holds a serialized array with sizes, dimensions, and image editor data. The attachment page URL is derived from the post_name and the parent post’s permalink, not from the file path.
This separation means you can change the file on disk without changing the attachment page URL, and you can change the attachment slug without moving the file. It also means that a broken attachment page can exist even when the file is perfectly intact. A crawler that follows the attachment page URL and gets a 200 with a broken image tag has no way to distinguish that from a real editorial page with a broken image.
To inspect the metadata for a specific attachment:
SELECT p.ID, p.post_name, pm.meta_key, pm.meta_value
FROM wp_posts p
LEFT JOIN wp_postmeta pm ON p.ID = pm.post_id
WHERE p.post_type = 'attachment'
AND p.ID = 12345
AND pm.meta_key IN ('_wp_attached_file', '_wp_attachment_metadata');
The serialized metadata is not queryable with normal SQL, but you can see the raw structure and confirm that the file path and the attachment page slug are independent values.
Common Failure Modes in Production Installs
Small-to-mid publishing teams usually hit three specific failure modes with attachment pages.
1. Sitemap and Index Bloat
If you use a sitemap plugin that includes attachment pages by default, every uploaded image gets a sitemap entry. A site with 10,000 images submits 10,000 thin URLs to search engines. The crawler spends budget on those URLs instead of your actual articles. You can check whether your sitemap includes attachments by looking for post_type=attachment in the sitemap XML or by running a quick crawl of your own sitemap with a tool like wget or curl.
The fix is usually a filter or a plugin setting that excludes attachment pages from the sitemap. In code, you can use the wp_sitemaps_post_types filter to remove the attachment post type from core sitemaps:
add_filter( 'wp_sitemaps_post_types', function( $post_types ) {
unset( $post_types['attachment'] );
return $post_types;
} );
This is a one-line change that prevents future sitemap bloat, but it does not fix URLs that are already indexed.
2. Soft 404s from Thin Templates
Even when the attachment page returns 200, the template may render so little content that search engines treat it as a soft 404. The default attachment.php in many classic themes shows the image, the caption, and a comment form. There is no article text, no related content, and no clear purpose for a reader who lands on the page from search.
You can test this by viewing the rendered HTML of an attachment page and counting the visible text. If the text is under 100 words and the page has no unique value, it is a soft-404 candidate. The fix is either to redirect attachment pages to the parent post or to the file URL, or to build a genuinely useful attachment template with context, metadata, and navigation. Most publishing teams choose the redirect because it is simpler and preserves crawl budget.
3. Orphaned Attachments After Parent Deletion
When you delete a parent post, WordPress does not automatically delete the attachment posts. The attachment posts remain with post_parent pointing to a non-existent post ID. The attachment page URL may return 404 because the parent is missing, but the attachment post still exists in the database. This creates a mismatch between the database state and the URL behavior.
You can find orphaned attachments with a SQL query:
SELECT a.ID, a.post_title, a.post_parent
FROM wp_posts a
LEFT JOIN wp_posts p ON a.post_parent = p.ID
WHERE a.post_type = 'attachment'
AND p.ID IS NULL;
These orphaned rows are not harmful by themselves, but they can confuse plugins that iterate over attachments, and they can produce unexpected 404s in crawl logs. A cleanup routine that deletes orphaned attachments or reassigns them to a valid parent is a reasonable maintenance task for a production install.
How to Decide: Redirect, Block, or Keep
The right choice depends on your editorial workflow and your archive strategy. There is no universal answer, but there are three defensible positions.
Redirect to the parent post. This is the most common choice for publishing teams. It preserves the link equity from any external links to the attachment page, sends readers to a useful page, and removes the thin page from the index. You can implement it with a template redirect in a child theme or a small plugin:
add_action( 'template_redirect', function() {
if ( is_attachment() ) {
global $post;
if ( $post && $post->post_parent ) {
wp_safe_redirect( get_permalink( $post->post_parent ), 301 );
exit;
}
}
} );
This redirect sends every attachment page to its parent post. If the parent post is missing, the redirect falls through and the attachment page returns its normal 404 or 200 behavior. You can extend the snippet to redirect to the file URL instead, but that sends readers to a raw image with no editorial context, which is rarely useful.
Block attachment pages with a 404 or 410. Some teams prefer to return a hard 404 for all attachment pages, even when the attachment post exists. This is a stronger signal to crawlers that the URL should be removed from the index. The downside is that any external links to attachment pages will land on a 404, which is a poor user experience. If you choose this route, make sure your 404 template is useful and includes a search form and links to recent articles.
Keep attachment pages and improve the template. This is the least common choice, but it can work for sites that publish photography, infographics, or other visual content where the attachment page has standalone value. The template needs to include the image at a reasonable size, the caption, the description, the parent post link, related images, and enough text to avoid a soft 404. This is more work than a redirect, and it only makes sense if your attachment pages have a real audience.

What the Crawl Logs Actually Show
If you have access to server logs or a crawl tool, look for the pattern of attachment URLs being requested repeatedly. A typical log entry looks like this:
66.249.66.1 - - [12/Sep/2024:08:14:22 +0000] "GET /2024/09/editorial-workflow-notes/newsroom-dashboard/ HTTP/2" 200 1842 "-" "Googlebot/2.1 (+http://www.google.com/bot.html)"
The 200 status with a small response size is the signature of a thin attachment page. If you see hundreds of these requests per week, the crawler is spending budget on URLs that will never rank. After you implement a redirect, the same URL should return a 301 and the crawler should follow it to the parent post. The log entry changes to:
66.249.66.1 - - [12/Sep/2024:08:15:02 +0000] "GET /2024/09/editorial-workflow-notes/newsroom-dashboard/ HTTP/2" 301 0 "-" "Googlebot/2.1 (+http://www.google.com/bot.html)"
That 301 is the signal you want. It tells the crawler that the attachment URL is permanently moved, and it consolidates any link equity into the parent post.
Checking Your Own Install
Before changing anything, run a quick audit. Use WP-CLI to count attachments, check the sitemap, and sample a few attachment URLs:
wp post list --post_type=attachment --format=count
wp option get permalink_structure
wp eval 'var_dump( wp_sitemaps_get_server()->get_sitemaps() );'
Then request a sample of attachment URLs with curl -I and note the status codes. If you see a mix of 200, 301, and 404, your attachment handling is inconsistent. That inconsistency is what confuses crawlers most: the same type of URL behaves differently depending on the parent post status, the theme template, and the plugin stack.
For a deeper look at how WordPress handles missing content in general, see What to Fix First When a New WordPress Site Says Nothing Found. The 404 path for attachment pages shares the same query and template fallback logic, but the attachment-specific rewrite rules add an extra layer of indirection.
FAQ
Why does WordPress create attachment pages at all?
Attachment pages are a legacy feature from the early WordPress architecture, when every uploaded file was treated as a post-like object with its own URL. The attachment post type still exists in core because themes and plugins rely on it for media metadata, even though the standalone attachment page template is rarely useful for modern publishing sites.
Do attachment pages hurt SEO?
They can, but not because of a penalty. The harm comes from crawl budget waste, index bloat, and soft-404 signals. A site with thousands of thin attachment pages gives search engines more URLs to crawl without adding any substantive content. Redirecting or blocking attachment pages usually improves crawl efficiency and consolidates link equity into real editorial pages.
What is the difference between an attachment page 404 and a normal 404?
A normal 404 occurs when the requested URL does not match any rewrite rule or when the main query finds no post. An attachment page 404 occurs when the rewrite rule matches but the attachment post is missing, or when the parent post is unavailable and the attachment inherits that unavailable status. The HTTP status code is the same, but the underlying query path is different.
Can I disable attachment pages without a plugin?
Yes. The template_redirect snippet shown earlier is a complete solution for redirecting attachment pages to their parent posts. You can add it to a child theme’s functions.php or to a small custom plugin. For blocking attachment pages entirely, you can use the same hook to return a 404 or 410 status instead of redirecting.
Next Step for Your Install
Run the audit queries, check your sitemap, and sample a dozen attachment URLs. If you find thin pages returning 200, implement the redirect and monitor the crawl logs for the 301 pattern. Then document the decision in your team’s editorial workflow notes so that future uploads follow the same rule. This is a small change with a measurable impact on crawl efficiency, and it removes one of the quietest sources of index noise in a self-managed WordPress install.