PHP Unserialize: Decode WordPress Options and Serialized Data

PHP Unserialize: Decode WordPress Options and Serialized Data

Unserialize WordPress `wp_postmeta`, PHP sessions and Laravel caches to readable JSON in the browser — arrays and scalars only, no local script.

31.08.2026
9 min read
Share this article:
PHPUnserializeWordPressDebuggingSerializationTutorial

Decode serialized PHP instead of reading raw tokens

A WordPress option_value, a wp_postmeta.meta_value, a PHP session blob or a Laravel cache dump often lands in your editor as a:3:{s:8:"blogname";…}. That string is the output of PHP serialize(). It is not JSON and not a minified bundle. The online PHP unserializer turns array and scalar tokens into readable JSON (or PHP array syntax) in the browser. It does not run PHP, does not instantiate class objects and does not upload the payload. This article covers the debugging workflow: where these blobs live, how to paste them safely and when you still need native PHP. For the wire format, JSON versus serialize and object injection, start with the PHP serialization guide. Front-end assets on the same WordPress site are a separate job, covered in WordPress minification.

Inspect wp_options, postmeta and transients without a local PHP script
JSON or PHP array output, indented by 2 spaces by default, and nothing leaves the tab
Arrays and scalars only: objects of type O and references of type R are rejected
Safer than PHP unserialize() on an unknown dump: no object execution
Round-trip arrays via php-serialize after you edit the readable JSON

Serialize and unserialize, two tools for one WordPress dump

serialize() writes and unserialize() reads, so FastMinify has one page for each

PHP serialize() emits a typed string. unserialize() rebuilds the value. FastMinify mirrors that split: php-serialize encodes JSON or PHP array syntax into a:/s:/i: tokens; php-unserialize decodes those tokens. Do not paste a serialized blob into the serializer, and do not paste JSON into the unserializer. Developer utilities that sit next to these pages live on the developer utilities hub.

Unserialize page: paste a:…, s:…, i:…, d:…, b:…, N;
Serialize page: paste JSON or array(…) / => syntax (see PHP serialize online)
Output format on unserialize: JSON (default) or PHP array syntax
Pretty JSON is for reading. For compact JSON, copy the output into minify-json
A minified JS file from a plugin is not serialize(): use an online JavaScript unminifier
Where WordPress actually stores serialize()

Core and many plugins call maybe_serialize() / maybe_unserialize(). If the value is a PHP array (or an object), it is stored in MySQL as a serialized string. Scalars (plain strings, numbers) stay as they are, so not every row has an a: prefix.

wp_options.option_value: site name, permalink structure, widget instances, plugin settings
wp_postmeta.meta_value: attachment sizes, custom fields, page builders
wp_usermeta / wp_commentmeta: same pattern, per user or comment
Transients (_transient_* options) often hold an array, while the expiry time sits in a separate timeout option
If the cell starts with O: followed by a class name, FastMinify rejects it, because that is an object, not an array
PHP unserialize() is a security boundary, and the browser tool is not PHP

In PHP, unserialize() on untrusted input can instantiate objects and run gadget chains (object injection). FastMinify parses the format in JavaScript. It never executes PHP, and it does not decode O: class objects or R: references. That is a limit and a safety property. Use it to inspect array dumps. Do not treat a successful decode as “this payload is safe to unserialize in production”.

Unknown dump: inspect it in the browser first, with no upload and no PHP process
If you must decode in PHP: unserialize($s, ['allowed_classes' => false]) (PHP 7+)
Never eval or wp-cli eval a blob you copied from a ticket
Option dumps can contain API keys, so a local tab is safer than an online unserializer that posts to a server

What the parser accepts and what WordPress rows look like

Type prefixes you will see in a typical option_value

Each token starts with a letter. FastMinify’s unserializer accepts the same subset it can serialize: null, bool, int, float, string, nested array. Objects and references are errors, not silent skips.

Before

a:3:{s:8:"blogname";s:10:"FastMinify";s:11:"description";s:22:"Local developer tools.";s:7:"WPLANG";s:5:"en_US";}

After

{ "blogname": "FastMinify", "description": "Local developer tools.", "WPLANG": "en_US" }
a:N:{…}: array with N key/value pairs (associative or indexed)
s:n:"…" is a string, where n is the byte length, not the character count of multibyte UTF-8
i: integer, d: float, b:0/b:1 bool, N; null
O:8:"stdClass" and R: / r: are not decoded here
A string cut short, such as s:3:"hello" without its closing semicolon, fails instead of corrupting the rest of the array. The tool does not compare the number with the text, so check it in PHP when it matters
Reading a nested wp_postmeta array

Attachment metadata and some custom fields (ACF relationship or checkbox fields, for example) are arrays of integers and strings, exactly the subset this parser handles. Paste the cell, click Unserialize and copy the JSON.

Before

a:2:{s:5:"width";i:1200;s:6:"height";i:630;}

After

{ "width": 1200, "height": 630 }
phpMyAdmin / TablePlus: copy the raw cell, not the truncated preview
WP-CLI wp option get … --format=json already unserializes in PHP, so use FastMinify when you only have the SQL dump
After decoding, the toolbar offers JSON (the default) or PHP array syntax, plus the indent size and spaces or tabs
The optional filters (drop nulls, empty arrays and empty objects, or sort keys) change the payload, so leave them off for a faithful inspection
Need compact JSON for a ticket: online JSON minifier on the copied output
Sessions, Laravel caches and the limit on objects

PHP session files and some Laravel cache drivers store serialize() payloads. If the value is an array of scalars, the browser tool works. If it is an Eloquent model, a Carbon instance or any O: class, FastMinify returns a clear error. That is expected: the tool does not pretend to be PHP’s unserialize.

Laravel Cache::put of a plain array usually gives a:, so paste and decode it
Laravel Eloquent models and custom DTOs give O:, so decode them in PHP with an allowlist, not here
Encrypted cookies and encrypt() payloads are not serialize() output, so decrypt them in the app first
igbinary and JSON cache stores are not PHP serialize(), so check the cache driver before pasting
Same honesty as the tool docs: no O:, no R:, no object execution

Unserializing in the browser with a concrete WordPress example

Using the PHP unserializer

Open the PHP unserializer, paste a single serialized string and click Unserialize. The output is JSON by default (indent 2, spaces). Switch to PHP array syntax if you are pasting back into a snippet. Everything stays in the tab, with no account and no server round-trip.

Accepted: null, booleans, integers, floats, strings and nested arrays
Rejected: class objects of type O, references of types R and r, and truncated strings. The number that announces the length is not checked
Options: JSON or PHP array output, include nulls (on by default), strip empty arrays and objects, sort keys, indent size, spaces or tabs
Not a WordPress SQL migration tool: do not hand-edit string length numbers in a dump
A widget instance in wp_options

A sidebar widget shows empty after a migration. The widget_* option is a serialized array. You need to see which keys survived, not guess from a 400-character cell.

1

1. Copy the raw option_value

From SQL or WP-CLI, copy the full string starting at a:. Truncated previews ending in … will fail to parse.

2

2. Paste into php-unserialize

Open php-unserialize and leave the output on JSON. If you see an error about an unknown format at O:, the widget stored an object. Stop here and use PHP with allowed_classes.

3

3. Edit the JSON and re-serialize only if you must write back

Fix the keys in the JSON, then encode it again with php-serialize. This round-trip works for the arrays and scalars this parser supports. It does not give a byte-identical copy of WordPress’s original string (key order, spaces). Prefer WP-CLI wp option update with JSON when you can.

A Laravel cache dump in Redis

Redis shows a value that starts with a:. You want to know which config keys are in the payload before you delete the key.

1

1. Copy the value as raw text

redis-cli escapes the quotes inside a value unless you use its raw output mode, so copy the value as raw text. If anything sits before the first a: or s:, such as the expiry timestamp that the Laravel file cache driver writes first, cut it.

2

2. Decode locally

Paste it into the unserializer. Nested arrays become JSON objects or arrays. Nulls stay if “Include null values” is on (the default).

3

3. Leave object payloads to PHP

An Illuminate\… class token will raise an error. That is the tool working as documented, not a broken Redis dump.

When you still need PHP (and how to round-trip arrays)

allowed_classes set to false, the PHP-side check

If the blob contains objects, or you are in a deployment script, decode in PHP without instantiating classes. Incomplete class objects tell you the class name without running constructors. FastMinify does not replace this safeguard.

Basic example

<?php // Inspect an untrusted serialize() dump without instantiating classes (PHP 7+). $raw = file_get_contents('option_value.txt'); $value = unserialize($raw, ['allowed_classes' => false]); var_export($value);
maybe_unserialize and WP-CLI for WordPress

Core already knows the format. maybe_unserialize() returns arrays as arrays, and WP-CLI prints JSON so you never edit length numbers by hand. Use FastMinify when you only have a SQL export or a paste from a ticket. Then write back through the WordPress APIs rather than a raw UPDATE of a tweaked serialize() string.

Basic example

# Read an option as JSON (WordPress unserializes in PHP). wp option get widget_text --format=json # Update from a JSON file instead of patching s:n:\"…\" in SQL. wp option update my_plugin_settings "$(cat settings.json)" --format=json
Round-trip in the browser, arrays only

Decode with php-unserialize, edit the JSON and encode with php-serialize. Nested JSON objects become PHP arrays, not O: objects. Sorting keys or stripping nulls and empty structures changes what you write back. The on-page docs say it plainly: this is not a byte-accurate WordPress SQL migration utility. For CSS and JS on the same site, use the WordPress minification guide, which is a different pipeline.

Basic example

// Browser loop (arrays/scalars only): // 1. Paste serialize() string → php-unserialize → JSON // 2. Edit JSON // 3. Paste JSON → php-serialize → new a:… string // Do not UPDATE wp_options with a hand-edited s:n:"…" prefix.

Conclusion

Paste the serialize() string, read the JSON and decide whether the payload is an array you can round-trip or an object that belongs in PHP. FastMinify runs that inspection locally and refuses O:/R:. It is not unserialize(), not WP-CLI and not a safe find-and-replace on MySQL dumps. For the format in depth, keep the PHP serialization guide next to this workflow.

Copy the full cell, because truncated strings fail to parse
Leave O: payloads to PHP with allowed_classes set to false
Do not hand-edit string length numbers in SQL
Round-trip arrays only: unserialize → JSON → serialize
Keep dumps in the browser; option_value can contain secrets
Share this article
Share this article: