Search and replace across the site
wp_search_replaceSearch and replace across the site's stored data, safe for serialized and JSON values; finding text without changing it is wp_search, one post is changed with wp_update_post. tables: posts (title, content, excerpt), postmeta, options, terms (names, descriptions, termmeta); default posts and postmeta. apply=false (default) is a dry run that returns a per-table preview; apply=true writes. Matching: serialized and JSON values are rewritten losslessly, and the CSS and caches Elementor builds from elementor_data (element cache with the rendered HTML, Markdown cache) are reset. Plain (non-regex) mode also finds the encoded forms WordPress and page builders store (JSON-escaped such as https://…, block attributes such as &, HTML entities such as &, and HTML inside block attributes), so "A & B" is found where a page stores "A & B", and writes the replacement in the form it found, as JSON inside block attributes. A serialized value holding a PHP object, a Serializable or enum record or a reference is left untouched (skipped_object_values), so no class is restored from stored data. Scope "text" (default): a page-builder page that a writer here writes (write_via in wp_get_builder_layout) changes only through that writer, in the texts, links and images it may change, under the field rules of wp_update_builder_element; its post_content copy is left out (copy_only). Matches in locked places (code, HTML, CSS, shortcodes, forms, placeholders, global parts, page code), and on pages the writer refuses as a whole, stay and are counted in locked_matches; scope "raw" reaches them. Fields a writer leaves are named in notes. A page whose page builder has no writer here, and a text a writer finds in none of its fields where the site shows post_content (SeedProd), are replaced as text (as_text, builder_pages_without_writer); a builder that keeps its own copy writes it over that at its next save. For an account without unfiltered_html, a post that WordPress's kses filter would store differently (an SVG, a style or a script dropped, a block attribute changed, in any field it filters) is not written and is named in notes. Scope "raw": the stored data as text everywhere, page-builder data and page code included (page-builder data needs unfiltered_html); a copy in post_content_filtered (SeedProd) is not read, so only post_content changes there until the page builder writes its copy back at its next save, and warnings names such pages. Undo: page-builder pages get undo points under one undo_token (undo_pages lists them). For pages a writer changes it holds their page-builder data and its copies; for pages changed outside a writer and in scope "raw" also post_content and the meta keys the call rewrites on them, except the code fields a page builder locks (custom CSS, for example): an undo leaves those as changed, and warnings names them. Posts without a page builder, titles, excerpts, options and terms are not in it, and the answer says so. Per call, at most 25 pages change through writers (next.builders continues) and at most 25 in scope "raw"; of the pages scope "text" changes outside a writer, up to 25 get an undo point, and the others, or any whose undo point cannot be recorded, are written without one and named in warnings (stop_at_undo_cap, allow_without_undo). Never touched: trash, auto-drafts, revisions (unless exclude_revisions=false), protected options and option names the option guard refuses, transients, the guid column, credential-like meta keys, widget rows, internal post types and taxonomies; rows the account may not read or edit are passed over silently. Protected "" meta keys are rewritten only for an account with manage_options and only when allow-listed (filter ab_mcp_pro_protected_meta_allowlist), never _wp_attached_file, _wp_attachment_metadata, _thumbnail_id or _wp_page_template; page-builder data (_elementor_data, panels_data, dslc_code, pagelayer-data, brizy, vcv-pageContent, mfn-page-items, tve_updated_post and more; filter ab_mcp_pro_markup_meta_keys) only for an account with unfiltered_html, on multisite a super admin. Writes go through the WordPress APIs (revisions created, serialization regenerated, caches invalidated), term names and descriptions through wp_update_term(). No slug is asked to change: a term shared by several taxonomies or with an empty stored slug is passed over, and slug_changes lists any slug a filter changed along with a name (term, old and new slug; up to 200, the rest in slug_changes_omitted). Paging: at most 5 000 000 ids per scan (10 000 per query, a tenth in regex mode; the terms table has three scans, the page-builder pages one, builders); next records where each scan stopped, and sent back as after it lets the next call continue without reading anything twice. Answer: per-table counts and previews; notes (up to 10 per table, notes_omitted the rest); warnings; skipped_object_values and skipped_unchecked_values (too large or too deep to walk: more than 64 levels or 12 nested serialized or JSON strings) count values, not rows, and the rest of such a row is still rewritten. Forwarded by AlphaBridge Connect to the one site this connection reaches.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| type | No | Post type filter for the posts table and the page-builder pages (postmeta is scanned for every post whose meta the account may read and edit); a call without the posts table ignores it (flags.type_ignored). Default any. | |
| after | No | The next object of a previous call (keys posts, postmeta, options, term_names, term_descriptions, termmeta, builders; each the id to continue behind). Default: start at the beginning of every table. | |
| apply | No | true writes the changes; false (default) returns the dry-run preview only. | |
| limit | No | Max matched rows processed per table (1–2000). Default 200. When truncated=true, next, sent back as after, continues there; notes say why a scan stopped, and only where the row limit stopped it does a higher limit take more rows (page-builder pages stay at 25 per call: table builders, scope raw, stop_at_undo_cap). Rows the policy passes over do not count. | |
| regex | No | true treats search as a PCRE regex (no delimiters; slower: every row of the id budget is read and tested in PHP, without a SQL prefilter). Matches the stored bytes only, without the encoded forms. In scope text, a page-builder page whose writer does not apply a pattern to its fields is left as it is and named in notes, with the way: scope "raw". Default false. | |
| scope | No | text (default): page-builder pages that a writer of this version writes are changed only in the texts, links and images their writer may change; matches in locked places are counted in locked_matches; the page-builder pages it changes get an undo point (those changed outside a writer up to 25 per call; warnings names the pages beyond). raw: the stored data as text everywhere, page code included (page-builder data needs unfiltered_html; a copy a page builder keeps in post_content_filtered, as SeedProd does, is not read), with an undo point for every page-builder page. | |
| search | Yes | Text to find (or PCRE pattern without delimiters when regex=true). | |
| tables | No | Tables to process: posts, postmeta, options, terms. Default ["posts","postmeta"]. | |
| replace | No | Replacement text. Default "" (removes the match). | |
| case_insensitive | No | Case-insensitive matching. Default false. | |
| stop_at_undo_cap | No | scope text: one call keeps undo points for up to 25 page-builder pages it changes outside a writer. Default false: the pages beyond them are written without one, as before, and warnings names them. true: the posts and postmeta scans stop before the first such page instead (truncated, with a note); next, sent back as after, continues there, so every page gets an undo point. | |
| exclude_revisions | No | true (default) skips post revisions; false includes them. | |
| allow_without_undo | No | true writes a page-builder page whose undo point would be over the size limit, without a way back. Default false: such a page is not written. Any other failure to record the undo point still refuses the page. Applies to scope raw and to the pages a writer changes; in scope text a page changed outside a writer is written as before when its undo point cannot be recorded, and warnings names it. |