How to Bulk-Replace Image and Attachment URLs in WordPress
You moved your uploads to a CDN, switched offload providers, or changed your domain — and now half your images point at the old URL. The files might be sitting in the new location perfectly, but every post, gallery, and page-builder block still references https://example.com/wp-content/uploads/... instead of https://cdn.example.com/.... That's a bulk image-URL replacement job, and doing it by hand or with a quick SQL UPDATE is how galleries and page-builder layouts break.
This post covers when you need to replace image URLs in WordPress, why the naive approaches are risky, and the safe way to do it — back up, dry run, replace, selectively apply, and undo if something looks off.
Why you'd bulk-replace image and attachment URLs
The image files and the image URLs are two separate things. Moving or re-pointing files doesn't update the references stored throughout your database. The common reasons you end up needing a bulk replace:
- Moving uploads to a CDN. You start serving
/wp-content/uploads/fromcdn.example.com(BunnyCDN, KeyCDN, Cloudflare, etc.), so every image base URL needs to change from your origin domain to the CDN host. - Moving media to a subdomain. Same idea — you split media onto
media.example.comorstatic.example.comto take load off the main site. - Switching offload-media providers. You move from one S3/offload plugin to another (or to a different bucket/region), and the stored URLs point at the old provider's endpoint.
- Changing your domain. A rebrand or migration changes
oldsite.comtonewsite.com, and attachment URLs are part of what has to follow. - Fixing http→https on media. You moved to SSL but old image references are still
http://, triggering mixed-content warnings. (We cover this end-to-end in Fix Mixed Content (HTTP→HTTPS) in WordPress.) - Restructuring upload paths. You change
WP_CONTENT_URL, move uploads out of the default folder, or reorganise the path and need every reference updated to match.
In all of these, the fix is the same shape: find the old image base URL everywhere it's stored, and replace it with the new one — safely.
Why hand-editing or naive SQL is risky
It's tempting to open phpMyAdmin and run something like UPDATE wp_posts SET post_content = REPLACE(post_content, 'old', 'new'). For a flat string that's stored as plain text, that works. The problem is that WordPress doesn't store most image references as flat text.
- Serialized galleries and meta. WordPress stores a lot of data — gallery shortcodes, image metadata, theme options — as serialized PHP arrays. Serialized strings carry a byte-length prefix, e.g.
s:42:"https://example.com/...image.jpg". If you change the URL length with a blindREPLACE, the prefix no longer matches the string, the data fails to unserialize, and your gallery, slider, or option silently breaks. (More on this in WordPress Search & Replace on Serialized Data, Safely and the serialized-data doc.) - Page-builder data. Elementor, Divi, Beaver Builder, and WPBakery store layouts as large serialized or JSON blobs in
postmeta. Image URLs are buried inside, often more than once per element. A naive query either misses them or corrupts the surrounding structure. - Postmeta and options. Featured-image and attachment relationships, plus offload-plugin metadata, live in
wp_postmetaandwp_options. Replace onlypost_contentand you'll fix the visible content while leaving thumbnails, srcset entries, and builder backgrounds pointing at the old host.
So the real requirement isn't "find and replace a string." It's "find and replace a string across the right tables, including inside serialized data, without breaking anything — and with a way back if it goes wrong." That's exactly what Update URLs is built for.
The safe approach with Update URLs
Here's the workflow that gets you from old image URLs to new ones without the 2 a.m. surprises.
1. Back up first
Before touching anything, take a backup. Update URLs has a built-in one-click database backup so you don't have to leave the screen or wire up a separate plugin. Run it, confirm it completed, then proceed. Even though you'll dry-run and can undo, a fresh backup is your floor.
2. Enter the old and new image base URLs
Set your search term to the old image base URL and your replace term to the new one. Work at the base-URL level, not individual files — replace the part that's common to every image:
- CDN move:
https://example.com/wp-content/uploads→https://cdn.example.com/wp-content/uploads - Subdomain move:
https://example.com/wp-content/uploads→https://media.example.com - http→https:
http://example.com/wp-content/uploads→https://example.com/wp-content/uploads
Keep the search string as specific as possible (include the path) so you only touch image references, not unrelated links. The general mechanics are in How to do search and replace text in WordPress.
3. Choose the right tables
Use the table picker to target where image URLs actually live — typically wp_posts (content), wp_postmeta (featured images, builder data, attachment meta), and wp_options (theme/plugin settings). You don't need to scan every table; narrowing to the relevant ones is faster and lower-risk. See How to run search and replace on selected tables.
4. Run a dry run
This is the step the naive approaches skip. A dry run scans for matches and shows you exactly what would change — how many rows in each table, and the before/after — without writing anything. Read it before you commit:
- Does the match count look sane for the number of images you have?
- Are the right tables showing hits (postmeta and options, not just posts)?
- Do any matches look like collateral you didn't intend?
Walk through it in How to do a dry run before search and replace.
5. Selectively apply
Update URLs handles serialized data correctly — it re-counts the byte-length prefix when the string length changes, so serialized galleries and page-builder blobs stay valid. After the dry run, selectively apply the changes you've confirmed rather than firing a blanket replace across everything. Apply, then move to verification.
6. Undo if it doesn't look right
If something's off after applying, use one-click Undo / Rollback to revert the operation. This is the safety net a raw SQL query simply doesn't have — there's no "undo" for a manual UPDATE. Between the dry run, selective apply, and rollback, you get to be cautious at every step. If you hit anything unexpected, the troubleshooting guide covers the common cases.
A note on CDN provider changes
CDN moves have an extra wrinkle: many offload/CDN setups store the rewritten URL in plugin-specific metadata and in the content, so you may have two or three base URLs in play (your origin, the old CDN host, the new CDN host). Replace them one base URL at a time, dry-running each pass, rather than trying to do it all at once. There's a dedicated walkthrough for this in How to change CDN providers. The same approach applies whether you're switching between CDNs or pointing media at a CDN for the first time.
Verify images load and regenerate thumbnails
Replacing the URLs doesn't move files — it only changes the references. So after you apply:
- Confirm the files exist at the new location. Open a couple of image URLs from the new base directly in a browser. If they 404, the files aren't where the new URL points and you need to fix the move (or revert) before going further.
- Hard-refresh and check pages. Load a post, a gallery, and a page-builder layout. Look for broken images and check the browser console for mixed-content or 404 errors.
- Clear caches. Purge your page cache, object cache, and CDN cache so visitors don't see stale references.
- Regenerate thumbnails if needed. Update URLs rewrites the stored URLs, including srcset sizes. It does not generate image files. If you changed the path structure (not just the host) and intermediate sizes are missing at the new location, regenerate them with a tool like Regenerate Thumbnails or
wp media regenerate. A pure host swap (origin → CDN serving the same paths) usually needs no regeneration.
If anything still looks wrong, you always have the troubleshooting guide and the one-click rollback to fall back on.
Conclusion
Bulk-replacing image and attachment URLs in WordPress is routine — until a blind SQL REPLACE corrupts a serialized gallery or leaves half your postmeta on the old host. The safe path is the same every time: back up, set the old and new image base URLs, pick the right tables, dry-run to see what changes, selectively apply, verify the images load, and undo if anything's off. Update URLs gives you each of those steps — including the dry run and one-click rollback that raw SQL can't. For the full mental model behind safe replacements, start with the pillar guide: WordPress Search and Replace: The Safe Guide. When you're ready, grab Update URLs.
FAQs
Will this move the actual image files?
No. Update URLs replaces the URLs stored in your database — it doesn't copy or move files. Make sure the images already exist at the new location (CDN, subdomain, or bucket) before you replace, then verify a few load directly.
Do I need to regenerate thumbnails afterward?
Usually not for a pure host swap, since the stored URLs (including srcset sizes) are rewritten in place. If you changed the upload path structure and intermediate image sizes are missing at the new location, regenerate them with Regenerate Thumbnails or wp media regenerate.
What about serialized galleries and page-builder data?
Update URLs handles serialized data correctly — it recalculates the byte-length prefixes when the string length changes, so galleries, sliders, and Elementor/Divi/WPBakery layouts stay valid. That's the failure mode a naive SQL REPLACE hits. See updating serialized data effectively.
Can I point my images at a CDN with this?
Yes. Replace your origin image base URL (e.g. https://example.com/wp-content/uploads) with your CDN host (e.g. https://cdn.example.com/...). For switching between providers or doing it in multiple passes, follow How to change CDN providers.
Can I undo the replacement if something breaks?
Yes. Update URLs has one-click Undo / Rollback to revert the operation, plus a built-in database backup you can take before you start — two safety nets a manual SQL query doesn't give you.