Published: April 13, 2026
The communication between different extension components (background scripts, content scripts, popups) has traditionally relied on JSON serialization. While reliable, JSON has limitations.
We are excited to announce that starting in Chrome 148, extension developers can opt-in to use the structured clone algorithm for message serialization instead of JSON! This modernization lets you send more complex data types between your extension contexts without manual serialization workarounds.
Why structured clone?
JSON serialization (via JSON.stringify under the hood) is functional, but it sometimes requires developers to jump through hoops when dealing with modern JavaScript types.
Here's a specific example you might've run into when developing an extension:
// Sending a Map with JSON serialization
const myMap = new Map([['id', 123]]);
// Arrives as {} on the other side!
chrome.runtime.sendMessage(myMap);
// Workaround: Convert Map to an Array of entries before sending
const message = Array.from(myMap.entries());
chrome.runtime.sendMessage(message);
// On the receiving side:
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
const receivedMap = new Map(message);
});
Some other situations where JSON fails that you might've had to workaround are
Set, BigInt, NaN and Infinity, Date, and Error Objects.
Using structured clone serialization means you can now send various objects that
were previously difficult or impossible to transmit over extension messaging.
For example, sending a Map object is now direct:
// Sending a Map with Structured Clone
const myMap = new Map([['id', 123]]);
// Arrives as a Map on the other side!
chrome.runtime.sendMessage(myMap);
// On the receiving side:
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
// message is already a Map instance!
console.log(message.get('id')); // 123
});
More supported types
Structured clone supports a wide array of other
types
such as File and Blob.
How to opt-in
To ensure backwards compatibility and prevent breaking existing extensions, this
feature is opt-in. You can enable it globally for your extension by adding a
single key to your manifest.json:
{
"name": "My Extension",
"version": "1.0",
"manifest_version": 3,
"message_serialization": "structured_clone"
}
If omitted, or on a Chrome version lower than 148, the browser defaults to its current JSON-based implementation for the extension.
By supporting the structured clone algorithm, we are bringing the extension
messaging API closer to alignment with standard web platform capabilities
(similar to postMessage used in Web Workers and iframe communication), giving
you more flexibility and power.
Interoperability and gotchas
While our structured clone serialization implementation supports many more types than JSON, there are a few architectural assumptions and incompatibilities with the implementation you should keep in mind.
Unsupported types
Shared objects like
SharedArrayBuffer
and transferring of
objects
like ArrayBuffer are not supported with our implementation.
SharedArrayBuffer will fail to serialize or deserialize (depending on the
situation), and attempting to send a transferable object like Uint8Array will
send a copy instead.
Extension to extension communication
We enforce matching serialization formats to ensure data integrity. Extensions
with mismatched serialization formats cannot communicate directly over
runtime.sendMessage or runtime.connect. For example, if extension A uses JSON
serialization and tries to message Extension B using structured clone, the
message will fail to send and the port will close (and vice versa).
Web page communication
Web Pages using externally_connectable will automatically adapt to the target
extension's serialization format. If your extension uses structured clone, web
contexts sending messages using the runtime API will use structured clone (and
vice versa) automatically. This means the web site and extension must be in sync
on their expected serialization format to prevent serialization errors.
Native messaging
Native messaging channels continue to always force JSON serialization.
Attempting to send structured-clone-only types (like a BigInt) to a native host
will fail before a message leaves your extension's context.
toJSON() methods
If you use classes or objects with custom toJSON() methods to perform custom
serialization (for example, sanitizing data by removing passwords before sending
an object), be aware that structured clone ignores toJSON(). It copies
property values directly. If you rely on toJSON() for custom serialization, some
manual work might be required before sending. For example:
class User {
constructor(name, password) {
this.name = name;
this.password = password;
}
// This will be ignored by structured clone!
toJSON() {
return { name: this.name };
}
}
const user = new User("Alice", "secret123");
// JSON -> {"name":"Alice"}
// Structured Clone -> { name: "Alice", password: "secret123" }
Is JSON serialization going away?
No! Chrome is committed to supporting both serialization formats for the foreseeable future.
Share feedback
We hope this new capability unlocks smoother and more powerful workflows for your extension development.
While we have created a test suite to validate functionality for our structured clone implementation, the web platform has a massive variety of objects. Try out this new feature and report any bugs or edge cases you encounter! Your feedback will help us improve the implementation for the entire community.