The PHP Unserializer parses PHP serialize format and converts it to readable formats: JSON (default) or PHP array syntax. Essential for inspecting PHP session data, cache entries, and database values stored in serialize format.
export function phpUnserialize(input: string): PhpValue { const text = input.trim(); let pos = 0; function read(n: number): string { const s = text.slice(pos, pos + n); pos += n; return s; } function readUntil(char: string): string { const start = pos; while (pos < text.length && text[pos] !== char) pos++; const result = text.slice(start, pos); pos++; // skip delimiter return result; } function parse(): PhpValue { const type = text[pos++]; if (pos < text.length && text[pos] === ':') pos++; switch (type) { case 'N': { pos++; // skip ';' return null; } case 'b': { const val = readUntil(';'); return val === '1'; } case 'i': { const val = readUntil(';'); return parseInt(val, 10); } case 'd': { const val = readUntil(';'); return parseFloat(val); } case 's': { const len = parseInt(readUntil(':')); pos++; // skip opening " const str = read(len); pos += 2; // skip "; return str; } case 'a': { const count = parseInt(readUntil(':')); pos++; // skip '{' const result: Record<string, PhpValue> = {}; for (let i = 0; i < count; i++) { const key = parse() as string | number; const value = parse(); result[String(key)] = value; } pos++; // skip '}' const keys = Object.keys(result); const isSequential = keys.every((k, i) => k === String(i)); return isSequential ? Object.values(result) : result; } case 'O': { const classLen = parseInt(readUntil(':')); pos++; // skip '"' const className = read(classLen); pos += 2; // skip '":' const count = parseInt(readUntil(':')); pos++; // skip '{' const result: Record<string, PhpValue> = { __class: className }; for (let i = 0; i < count; i++) { const key = parse() as string | number; const value = parse(); result[String(key)] = value; } pos++; // skip '}' return result; } default: throw new Error(`Unknown PHP serialize type '${type}' at position ${pos}`); } } if (text === 'N;') return null; const result = parse(); if (pos !== text.length) { throw new Error(`Trailing garbage at position ${pos}: "${text.slice(pos, pos + 20)}"`); } return result;}
The unserializer properly handles UTF-8 multibyte strings by using byte offsets (not character offsets), ensuring compatibility with PHP’s native unserialize() function.
For WordPress debugging:
Get serialized value: get_option('option_name')
Paste into PHP Unserializer
View in JSON format for easy inspection
Convert to PHP array syntax if you need to edit and re-serialize
The unserializer does NOT execute PHP code or instantiate classes (safe for untrusted input)
Object properties (public, protected, private) are all treated as regular properties
Custom serialization methods (__sleep, __wakeup, __serialize) are not invoked
Very deeply nested structures may cause stack overflow