ℹ Disclaimer: Content may contain affiliate links, WPThink.com may earn a commission from qualifying purchases.
Why Broken Image Links Occur After a WordPress Export
The way images break usually reveals the real fault line.
A homepage may load perfectly while product galleries turn blank, or every post may show the same empty placeholder. That difference matters. Broken images after export are rarely random; the failure pattern is often the fastest diagnostic clue.
When only some files fail, the problem usually sits in paths, attachment records, or missing folders tied to specific dates, sizes, or offloaded media. When everything fails, the cause is more often global: the old domain still embedded in URLs, a CDN origin mismatch, blocked hotlinking, bad permissions, or an uploads location WordPress no longer recognizes. Panic wastes time; pattern recognition usually shortens the fix.
- All images broken: suspect domain rewrite, CDN/origin, permissions, or uploads path settings.
- Only certain posts or sizes broken: suspect partial media copy, missing thumbnails, or year/month directory gaps.
What the export actually moved
A WordPress export is usually only XML
A standard Tools → Export file can look complete because it lists posts, pages, menus, custom fields, and attachment records. Those attachment entries are database content: filenames, captions, GUIDs, and URLs. They are not the actual image binaries stored in /wp-content/uploads/.
When that XML is imported elsewhere, WordPress may rebuild media library entries while still pointing to files that never arrived. The result is deceptive: content imports cleanly, image blocks exist, and alt text survives, yet nearly every image returns 404 or still references the old domain.
Three very different outcomes
- Content export: moves structured content and media references.
- Full migration: moves the database and uploads, themes, plugins, and often server-level configuration.
- Static export: generates HTML and copies assets only if the exporter successfully crawls or bundles them.
A fast verification step is to inspect the destination for real upload folders such as /wp-content/uploads/2024/05/. If those files are absent, the failure is not URL rewriting yet; the image files never moved.
Seeing attachment posts after import does not prove the images exist on disk. WordPress can display media metadata while the underlying files are missing or still hosted on an unreachable origin.
When the files are present but the links are wrong
A frequent post-export surprise is this: the image files exist in wp-content/uploads, yet pages still call the old location. Requests may still point to a previous domain, a staging subdomain, a retired CDN hostname, or an earlier uploads structure such as /files/ instead of /uploads/.
Where stale references usually hide
WordPress does not store image URLs in only one place. A simple database search may fix visible post content while leaving other layers untouched, especially if the goal is to preserve correct permalink behavior after the move.
- Serialized metadata: attachment sizes, gallery settings, widget data, and builder fields can break if replaced with non-serialization-aware tools.
- Generated markup: cached page output, block HTML, and theme or builder templates may still contain the old hostname.
- Derived image data:
srcset, resized variants, and WebP/AVIF references can continue serving legacy paths.
A reliable check compares the browser’s requested image URL with the file’s actual server path. If the file opens directly by path but the page source calls another host or directory, the problem is reference drift, not missing media.
For that reason, partial URL replacement often appears successful while broken images persist in only some posts, sizes, or templates.
When the library points off-site
A common trap is assuming every item visible in Media Library exists under /wp-content/uploads/. In many sites, WordPress stores only the attachment record while the actual file lives on S3, a CDN pull zone, or another object store.
The quickest check is the image URL itself. If the host is not the WordPress domain—or uses a CDN CNAME such as media.example.com—the export may be complete even though missing images in a static export suggest otherwise.
Look for these signs:
- Offload plugins such as WP Offload Media or custom S3 integrations
- Attachment URLs in
wp_postmetapointing to remote domains guidvalues and generatedsrcsetentries using a non-local host- An empty or partial
uploadsdirectory despite a full media library
If the origin is remote, the fix is usually not re-exporting WordPress. The missing step is exporting, syncing, or granting access to the remote bucket or CDN origin that actually holds the binaries.
Why the full image works while variants fail
A successful load of the original attachment URL proves surprisingly little. WordPress rarely serves that file alone. Posts usually reference generated sizes such as -150x150, -768x, or theme-specific crops stored beside the original and indexed in attachment metadata.
If those derivatives were never created, were deleted, or their metadata still points to old filenames, the main image can open normally while thumbnails return 404 errors.
Check what the page actually requests
The browser may be loading more than a single img src:
srcsetcan call missing intermediate sizessizescan select a nonexistent crop at certain breakpoints<picture>markup may point to WebP or AVIF files that were not generated on the destination- lazy-loading scripts may swap in
data-src,data-srcset, or CDN URLs after page render
This is why source inspection matters more than testing only the original file in a tab.
What to verify
- Compare the rendered HTML with the files inside
/uploads/ - Inspect attachment metadata for missing size entries
- Confirm image optimization plugins recreated WebP/AVIF companions
- Regenerate thumbnails if theme sizes changed or derivatives are absent
- Disable lazy-load or optimization layers temporarily to expose the real request path
In many migrations, the broken asset is not the image itself but a secondary version the page expects.
When images are stored outside the editor
Some breakage is selective because the front end is not reading from post_content at all. Builders, gallery plugins, theme settings, and custom fields often keep image references as attachment IDs, serialized arrays, JSON, or hard-coded URLs inside metadata and options. A post can import cleanly while a hero banner, archive card, or reusable block still points to a missing object.
Where the reference may live
postmetafor builders, repeaters, sliders, and gallery fieldstermmeta,usermeta, oroptionsfor category images, author boxes, headers, and site-wide design settings- plugin custom tables for layout libraries, carousels, or template systems
A useful test is to compare the stored value with the rendered HTML. If metadata still holds a valid attachment ID but the page outputs an old URL, the rendering layer, cached markup, or URL transformation logic is stale. If the HTML is empty, the dependent object itself may be missing; this is common during checks for missing ACF image content.
Plugin export tools also differ sharply. Some move field values but omit field groups, related terms, reusable templates, or custom-table records that the front end expects. In those cases, the upload exists, yet the page component that should resolve it never reconstructs the final image tag.
Read the response, not the symptom
Let the request decide
A broken image is not automatically a bad link. The browser Network panel shows whether the page requested the wrong file or the server mishandled a valid request. The strongest evidence is the combination of Request URL, Status, Content-Type, and any browser blocking message.
- 404 or 410 usually indicates a real path error: a bad relative path, missing
/uploads/year/month/segment, or a case mismatch on case-sensitive hosts (Header.PNGis notheader.png). - 301/302 often exposes hidden rewrite problems, especially when media redirects to an old domain or a stripped path.
- 403 points to delivery controls rather than export damage: permissions, hotlink protection, signed URLs, firewall rules, or CDN policy.
- 200 can still fail when the server returns the wrong MIME type. An image URL serving
text/htmloften means an error page is being delivered successfully. - CSP or CORS errors mean the file may exist, but the browser is not allowed to fetch it from that origin.
- Stale CDN cache can preserve old responses after the origin is fixed; compare origin headers and CDN headers before rewriting links.
A 404 on the exact requested path usually proves a linking error. A 403, blocked CSP/CORS request, or 200 with the wrong Content-Type usually does not.
Classify the break before touching data
-
Open one failed URL directly
Status and headers show missing file, blocked delivery, or wrong host.
-
Compare original and variant URLs
A working full-size with broken thumbnails points to generated sizes, srcset, or derivative formats.
-
Check disk against attachment metadata
If files exist but paths differ, the fault is mapping, not transfer.
-
Sample one good post and one bad post
Patterns by post type, date, or field isolate theme, meta, or migration scope.
-
Queue fixes last
Search-replace, regeneration, plugin toggles, and re-export come after classification.
Avoid starting with a global search-replace or a fresh export. Early edits can erase clues and make storage, metadata, and delivery failures look identical.
Diagnosis Before Repair
Broken image links stop looking mysterious once the failure is named correctly. A missing upload, stale attachment metadata, offloaded host mismatch, absent derivative, and delivery-layer block each leave different traces—and each requires a different repair.
That is why the fastest path is classification first: inspect the exact URL, file presence, metadata, generated sizes, and HTTP response before changing anything. Precision prevents destructive bulk fixes and turns migration cleanup into a short, bounded task.