WP Serial Fix

Change WordPress URLs without breaking your site.

A raw SQL find-and-replace on a WordPress database looks like it worked, then widgets, theme settings, and page builder layouts quietly disappear. The culprit is PHP serialization: it records the length of every string, and your replacement changed the text but not the number. Paste the value here and replace it the safe way, or repair data a bad replace already corrupted.

Everything runs in your browser. Your data is never uploaded. Works offline after your first visit.

🧩 The bug that eats WordPress migrations

WordPress stores structured settings (widget layouts, theme options, page builder content) as PHP serialized strings. A serialized string looks like this:

s:18:"http://old.example";

The 18 is the exact byte length of the text between the quotes. Now imagine you move the site and run a database-wide find and replace, http://old.example becomes https://new.longer.example. The text changes, the number does not:

s:18:"https://new.longer.example";   ← length says 18, text is 26

PHP reads exactly 18 bytes, hits data where it expected a closing quote, and gives up. WordPress gets false back instead of the saved structure, so the setting can appear empty. The page may lose widgets or layout data without pointing clearly to the damaged value.

πŸ”§ How the safe replace works

This tool follows the same serialization-safe principle as WP-CLI, except it works on values already in your browser and never connects to the database. It parses the serialized value into its structure, performs the replacement inside each string, and re-emits the data with every length prefix recomputed from the actual byte length. Multibyte characters are counted correctly (an accented letter is two bytes, an emoji is four), and nested serialized strings are handled too.

Paste a bare value or a whole column of them (one per line). Plain, non-serialized text is replaced normally and labeled as such, so you can run mixed content through in one pass.

🩹 Repair mode, for when it already broke

If a previous replace changed text without updating the length prefixes, repair mode follows the array and object structure and recomputes those lengths. It checks the completed result before returning it. If the value is truncated, malformed in another way, or has more than one possible repair, the tool leaves it unchanged instead of guessing.

πŸ—ΊοΈ The safer migration, start to finish

  1. Back up the database first. Always. This tool helps with values, not with backups.
  2. Export the tables, or copy the specific wp_options / wp_postmeta values you need to change.
  3. Run the old to new replacement here in search and replace mode.
  4. Paste the corrected values back, or import the corrected export.
  5. If you are cleaning up after a replace that already ran, use repair mode on the affected values.

For a whole live database at once, the command-line wp search-replace is still the right tool. This page is for the common middle ground: a handful of values, a single stubborn option, a page builder layout, or a cleanup, without setting up WP-CLI or trusting a value to a website you do not control.

πŸ’¬ Frequently asked questions

No. Parsing, replacing, and repairing all happen in your browser with JavaScript. There are no network requests after the page loads, which matters when the value you are pasting came out of a production database. You can read the small, dependency-free engine to confirm it.

Yes. Arrays, objects, references, custom-serialized objects, nested structures, and serialized strings inside other strings are supported. Custom object payloads are preserved as opaque data rather than searched.

For a full database, use wp search-replace "old" "new" from WP-CLI, which streams every table safely. This tool is for values you have in hand, and for repairs.

Yes. docs/serial.js is a dependency-free ES module: parse, serialize, isSerialized, strictReplace, and repair. MIT licensed.

🌱 Why I built this

I built this after dealing with serialized options during WordPress moves. For a few values, I wanted a small tool I could inspect, run locally, and use without giving it database access.