What a relief! We have just resolved a major migration challenge for a brand’s website, restoring images across more than 1,000 pages. If you need to fix broken images from S3 after moving a WordPress site, this is exactly how we did it. It was not a standard migration: it needed a close look at how the site handled its media 🙂.
Why the images broke
After the brand moved to a new host, they found broken image links (404 errors) all over the site. The cause was an unusual earlier setup: media had been offloaded to an AWS S3 bucket with the WP Offload Media plugin, but the bucket did not use the standard /uploads/ path structure.
So the image addresses in the WordPress database pointed to s3://[bucket-name]/year/month/image.jpg instead of the expected https://[brand’s-website-URL]/wp-content/uploads/year/month/image.jpg on the new server. The new host simply could not find the files.

How to fix broken images from S3, step by step
There was no quick fix. It took a careful, four-stage approach:
1. Find the exact old paths
First, we identified the exact, non-standard S3 URL patterns saved in the WordPress database. Getting this right mattered, because the search-and-replace at the end depends on it. Open a few broken images in your browser’s developer tools and note precisely what the database is asking for.
2. Download everything from the S3 bucket
Using Cyberduck, which connects straight to S3, we downloaded all the nested year/month folders and their contents, keeping the folder structure exactly as it was.
3. Put the files where WordPress expects them
Next, we uploaded the files into the standard wp-content/uploads/ folder on the new host with FileZilla, merging them with the media already there so nothing was overwritten.
4. Update the image addresses in the database
The images started to show after the file transfer (most likely because the plugin fell back to local files once the S3 connection was gone), but the lasting fix was a database-wide search-and-replace. We updated every remaining s3://[bucket-name]/ address in the wp_posts and wp_postmeta tables to the correct https://[brand’s-website-URL]/wp-content/uploads/ path.
If you have command-line access, WP-CLI’s search-replace command does this safely: run it with --dry-run first to see how many rows will change, take a database backup, then run it for real. Clear any caching plugin and your CDN cache afterwards.
How to stop it happening again
- Before a migration, check whether media is offloaded to S3 or another cloud store, and note the bucket path settings.
- Keep a full copy of
wp-content/uploadson the server, even when media is offloaded. - After moving, crawl the site for 404 images before you point the domain at the new host.
- Choose a host with good support for moves like this. Our list of the best web hosting in Nigeria covers the options.
Questions we get about broken S3 images
Why do my images show 404 errors after moving host?
Usually because the database still points to the old location, often a cloud bucket or the old domain, while the files now live somewhere else, or were never copied at all.
Can I fix broken images from S3 without WP-CLI?
Yes. A plugin such as Better Search Replace does the same search-and-replace from the WordPress dashboard. Take a database backup first either way.
Do I still need WP Offload Media afterwards?
Only if you want to keep serving media from S3. If you move the files back to your server as we did, you can switch it off once the database addresses are updated. Test on a staging copy first.
The result
Being able to fix broken images from S3 across a site this size, and seeing every image load from the brand’s own website again, was incredibly satisfying. The fix improved the user experience, strengthened image SEO and showed again why careful planning matters in every website migration.
Stuck with a tricky migration of your own? We handle moves, hosting and fixes as part of our web & app development service, so get in touch. And if you have faced a cloud storage setup like this, share your tips in the comments!
I tried it, and it worked. Impressive how people come up with solutions to problems like this