Action Message Format
The Action Message Format (AMF) is a compact binary format developed by Adobe Systems Incorporated for serializing ActionScript object graphs, enabling the persistence of application state across sessions or the transmission of strongly typed data between client-side Adobe Flash applications and server-side services.[1] Primarily utilized in Rich Internet Applications (RIAs) built with Flash and Flex, AMF facilitates remote procedure calls (RPC) over protocols such as HTTP or RTMP by encoding complex data structures like numbers, strings, arrays, and objects into an efficient, type-preserving representation.[1] Introduced as AMF 0 with Flash Player 6 in 2001, the format provided foundational support for 16 core data types and object references to manage redundancy and circular dependencies in serialized graphs.[1] AMF 3 followed in 2006 alongside Flash Player 9 and ActionScript 3.0, enhancing efficiency through optimizations like variable-length integer encoding, reference tables for strings and traits, and expanded type support including XML documents, byte arrays, vectors, and dictionaries.[2] These versions ensured backward compatibility, with AMF 0 remaining supported for legacy applications while AMF 3 addressed the demands of more advanced scripting features.[2] AMF's design emphasized compactness and type fidelity, making it suitable for real-time data exchange in environments like video streaming via Real-Time Messaging Protocol (RTMP) or web service integrations.[1] Although tied to the Adobe Flash ecosystem, which reached end-of-life in 2020, AMF continues to be referenced in legacy systems and open-source implementations.[2]Introduction
Purpose and Applications
The Action Message Format (AMF) is a compact binary format designed for serializing ActionScript object graphs, XML data, and messages to facilitate communication between Adobe Flash clients and servers.[1][2] It enables the efficient persistence and retrieval of application state across sessions or between endpoints, supporting strongly typed data exchange in a lightweight manner.[1][2] AMF's primary applications lie in remoting scenarios, where it powers asynchronous data exchange between Flash applications and remote services, such as invoking server-side operations from client-side code.[1] In streaming protocols like Real-Time Messaging Protocol (RTMP), AMF transmits structured data payloads efficiently over networks, minimizing bandwidth usage for real-time applications like video streaming and live data feeds.[1] AMF0 and AMF3 represent the core versions, with AMF3 offering optimizations like integer compression and string interning for enhanced performance.[2] Compared to text-based formats such as XML or JSON, AMF provides superior compactness and serialization speed, as its binary encoding reduces payload size and parsing overhead, making it ideal for binary transport in resource-constrained environments.[1][2] This efficiency supports remote procedure call (RPC)-style interactions in Flash, where developers specify target URIs for operations and handle responses via callback mechanisms, streamlining client-server integration without verbose markup.[1][2]Historical Context
The Action Message Format (AMF) originated in 2002 when Macromedia released Flash Player 6 on March 15, introducing AMF0 as a binary serialization mechanism to support ActionScript 1.0 object graphs in Flash Remoting for client-server communication.[3] This format enabled efficient exchange of structured data between Flash applications and backend services, addressing the limitations of text-based protocols at the time. AMF0 retained strong typing and object structure, making it suitable for early rich internet applications.[1] In June 2006, Adobe—following its acquisition of Macromedia in 2005—introduced AMF3 with Flash Player 9 and ActionScript 3.0, enhancing performance through new data types like traits for dynamic classes and optimizations such as variable-length encoding and reference tables to reduce payload sizes for object-oriented programming.[2][4] This evolution improved efficiency in handling complex data structures, aligning with the growing demands of interactive multimedia.[2] Key milestones in the 2000s included AMF's integration into the Real-Time Messaging Protocol (RTMP), developed by Macromedia in 2002 for Flash Media Server to enable real-time video streaming, where AMF encoded headers, commands, and metadata for low-latency delivery.[5] AMF also gained traction in enterprise environments, notably through Flex Data Services (later rebranded as LiveCycle Data Services), released by Macromedia in March 2004 to provide Java-based remoting and data synchronization using AMF for Flex applications.[6] In December 2007, Adobe open-sourced BlazeDS, a high-performance framework built on AMF for messaging and remoting in Java backends, further promoting its adoption in scalable web services.[7] After Adobe announced the end-of-life for Flash Player on December 31, 2020, AMF transitioned to legacy status, with support ceasing for browser-based Flash but persisting in server-side and non-browser contexts. As of 2025, AMF remains in use for niche applications, particularly in RTMP-based live streaming for metadata handling and in backward-compatible systems like ColdFusion integrations for legacy Flex components.[8][9]Format Specifications
Packet Structure
The Action Message Format (AMF) packet is a self-contained binary stream designed for efficient serialization and transmission of ActionScript object graphs. It begins with a 2-byte version identifier in unsigned 16-bit integer (U16) format, which specifies the AMF encoding version: 0x0000 for AMF0 and 0x0003 for AMF3.[1][2] This version header ensures compatibility and directs the decoder to the appropriate value encoding rules for the remainder of the packet. The packet structure follows the version with a 2-byte unsigned integer indicating the number of optional context headers (up to 65,535), each serving as metadata for the session.[1] A typical header includes a UTF-8 encoded name, a 1-byte "must-understand" flag, a 4-byte unsigned integer for the value length, and the AMF-encoded value itself.[1] After all headers, a 2-byte unsigned integer denotes the number of messages (also up to 65,535), with each message comprising a UTF-8 target URI, a UTF-8 response URI (potentially empty), a 4-byte message length, and the AMF-encoded payload.[1] This layout allows AMF packets to encapsulate multiple independent messages in a single stream. Within headers and messages, the AMF-encoded values form the core payload, consisting of one or more 1-byte type markers followed by variable-length data tailored to the marker's type, such as IEEE-754 double-precision numbers or UTF-8 strings.[1] These markers enable the representation of complex, nested structures like objects and arrays, where properties or elements recursively contain further AMF values, terminated by specific end markers (e.g., 0x09 for object end).[1] The format supports object graphs by allowing arbitrary nesting without predefined schema, facilitating the serialization of hierarchical data in a compact binary form. Packet boundaries are enforced through the explicit length fields in headers and messages, ensuring reliable parsing without additional delimiters.[1] This design also accommodates multi-message support, enabling protocols like RTMP to transmit several AMF-encoded operations in one packet for streamlined communication.[1] While the overall packet organization is consistent across versions, AMF3 introduces efficiencies such as reference counting for repeated structures, reducing redundancy compared to AMF0.[2]AMF0 Details
The Action Message Format version 0 (AMF0) is identified by a 16-bit unsigned integer version header set to 0, encoded as the bytes 0x00 0x00 at the beginning of an AMF packet.[10] This format was designed to serialize object graphs from ActionScript 1.0 and 2.0, preserving strong type information while enabling efficient binary transmission over networks.[10] AMF0 employs strict typing through a set of 16 core type markers, each a single byte (U8) that precedes the encoded data and indicates the type, such as 0x00 for numbers or 0x02 for strings.[10] Strings in AMF0 are encoded in UTF-8 format, prefixed by a 16-bit length indicator for strings up to 65,535 bytes or a 32-bit length for longer ones.[10] Numeric values use the IEEE 754 double-precision floating-point representation, consisting of 8 bytes to handle a wide range of real numbers with sufficient precision for typical ActionScript applications.[10] Objects in AMF0 are serialized as a sequence of key-value pairs, where each key is a UTF-8 string followed by its corresponding value encoded according to its type marker.[10] The object terminates with an empty string key (two zero bytes for the length, followed by no characters) and an end-of-object marker (0x09).[10] Unlike later formats, AMF0 lacks class traits for defining object structures, requiring full re-encoding of properties for each instance, and while it supports object references via a 16-bit index (up to 65,535 unique objects), this mechanism is limited to avoiding duplication within a single serialization context.[10] A key limitation of AMF0 is its lack of support for XML literals, such as those introduced in ActionScript 3.0's E4X syntax, and it does not accommodate advanced types from ActionScript 3.0, restricting its use to earlier language versions.[10] This results in verbose encoding for complex object graphs, as repeated structures must be fully expanded without shared trait definitions, increasing payload size and processing overhead in scenarios involving deeply nested or shared data.[10]AMF3 Details
AMF3 represents an evolution of the Action Message Format, specifically tailored for ActionScript 3.0 and the Adobe Virtual Machine Plus (AVM+), enabling more efficient serialization of complex object graphs including new language features.[2] It introduces optimizations such as variable-length encoding and reference mechanisms to reduce payload size compared to earlier versions, while maintaining backward compatibility through distinct version identification.[2] The AMF3 packet is identified by its version header, consisting of the two bytes0x00 0x03, which precede the encoded data types and specify the use of AMF3 rules for interpretation.[2] This header ensures decoders can apply the appropriate encoding scheme, supporting class-based objects that align with ActionScript 3.0's object-oriented paradigm, including typed classes with both static and dynamic properties.[2]
A core enhancement in AMF3 is the adoption of unsigned 29-bit integers (U29) for encoding sizes, lengths, and markers, allowing values up to 2^29 - 1 (approximately 536 million) in a compact variable-length format that minimizes byte usage for smaller numbers.[2] To further optimize serialization, AMF3 employs three implicit reference tables—one for strings, one for objects, and one for traits—that track previously serialized items, enabling subsequent references via dedicated markers rather than full re-encoding, thus avoiding duplication in object graphs.[2] Trait definitions, encoded with a class name followed by a count of sealed (static) properties and optional dynamic member names, facilitate the representation of class structures; these traits can themselves be referenced to reuse definitions across multiple instances.[2]
For arrays, AMF3 unifies handling under a single type marker (0x09), distinguishing between dense arrays—where elements are accessed via ordinal numeric indices—and associative arrays (maps) based on the structure following the marker.[2] A dense array begins with a U29-encoded length, followed by inline values for indices 0 to length-1; if the initial U29 is 0, it signals an associative array, where alternating string keys (U29 length + UTF-8) and values follow until an empty string key terminates the sequence.[2] This approach allows flexible representation of both array types without separate markers, leveraging U29 for efficient length indication.[2]
AMF3 also provides native support for serializing E4X XML nodes directly as a distinct type (marker 0x0B), encoding the XML document in UTF-8 format while preserving structure and allowing references to avoid redundant transmission, in contrast to AMF0's limitation to string representations of XML.[2]
Data Types and Encoding
Core Data Types
The Action Message Format (AMF) supports a range of core data types, each identified by a one-byte marker that precedes the encoded representation, enabling compact binary serialization of ActionScript values. AMF0 and AMF3 define overlapping yet distinct sets of types, with AMF3 introducing optimizations like integer types and reference mechanisms to reduce redundancy in object graphs.[1][2] In AMF0, there are 11 primary data types, plus reserved markers, designed for basic ActionScript serialization such as numbers, strings, and objects. The following table summarizes the AMF0 core data types, their markers, and basic representations:| Marker (Hex) | Type Name | Basic Representation |
|---|---|---|
| 0x00 | Number | 8-byte IEEE-754 double-precision floating-point value. |
| 0x01 | Boolean | 1-byte unsigned integer (0x00 for false, non-zero for true). |
| 0x02 | String | 2-byte unsigned length (U16) followed by UTF-8 bytes (up to 65,535 bytes). |
| 0x03 | Object | Sequence of property name-value pairs ended by Object End marker. |
| 0x05 | null | No additional data. |
| 0x06 | undefined | No additional data. |
| 0x07 | Reference | 2-byte unsigned index (U16) to a prior object. |
| 0x08 | ECMA Array | 4-byte unsigned count (U32) followed by name-value pairs like an Object. |
| 0x0A | Strict Array | 4-byte unsigned count (U32) followed by that many values. |
| 0x0B | Date | 8-byte milliseconds since Unix epoch (double) plus 2-byte timezone offset (reserved). |
| 0x0F | XMLDocument | 4-byte unsigned length (U32) followed by UTF-8 XML bytes. |
| Marker (Hex) | Type Name | Basic Representation |
|---|---|---|
| 0x00 | undefined | No additional data. |
| 0x01 | null | No additional data. |
| 0x02 | false | No additional data. |
| 0x03 | true | No additional data. |
| 0x04 | integer | Signed 29-bit integer via U29 encoding (values beyond range use double). |
| 0x05 | double | 8-byte IEEE-754 double-precision floating-point value. |
| 0x06 | string | U29 length followed by UTF-8 bytes or U29 reference index. |
| 0x07 | XMLDocument | U29 length followed by UTF-8 bytes or reference index. |
| 0x08 | date | U29 milliseconds since epoch or reference index (no timezone). |
| 0x09 | array | U29 count for dense portion, then associative pairs, or reference. |
| 0x0A | object | Traits info (U29) followed by properties, or reference to traits/object table. |
| 0x0B | XML | U29 length followed by E4X UTF-8 bytes or reference index. |
| 0x0C | ByteArray | U29 length followed by raw bytes or reference index. |
| 0x0D | vector-int | Fixed-type vector of 32-bit integers with U29 length. |
| 0x0E | vector-uint | Fixed-type vector of unsigned 32-bit integers with U29 length. |
| 0x0F | vector-double | Fixed-type vector of doubles with U29 length. |
| 0x10 | vector-object | Fixed-type vector of objects with class name and U29 length. |
| 0x11 | dictionary | U29 weak keys flag, U29 length, then key-value pairs or reference. |
Encoding and Decoding Mechanisms
The encoding process in Action Message Format (AMF) begins with a single-byte type marker that identifies the data type, followed by a type-specific payload containing the serialized data.[1][2] For basic types in AMF0, such as numbers, the payload consists of an 8-byte IEEE-754 double-precision floating-point value encoded in network byte order (big-endian).[1] Booleans use a single byte where zero indicates false and any non-zero value indicates true, while strings are prefixed with a 16-bit unsigned integer length (in network byte order) followed by UTF-8 encoded characters, limited to 65,535 bytes.[1] Complex structures like objects and arrays are handled recursively: objects consist of zero or more name-value pairs (string key followed by value), terminated by an empty string marker (0x00 0x00 0x09), and arrays include a 32-bit count followed by the elements.[1] In AMF3, the encoding introduces optimizations for compactness, including U29 (unsigned 29-bit integer) representation for lengths, counts, and references.[2] U29 values are encoded in 1 to 4 variable-length bytes, where the most significant bit of each byte (except the last) is set to 1 to indicate continuation, and the lower 7 bits carry data; the maximum value is $2^{29} - [1](/page/1) (536,870,911).[2] To decode a U29, bytes are read sequentially until a byte with the high bit cleared is encountered, then the value is computed as \sum_{k=0}^{m-1} ((b_k \land 0x7F) \times 128^{m-1-k}), where b_k are the m bytes read (with the first byte b_0 being the most significant chunk).[2] For example, integers in AMF3 use U29 for values up to \pm 2^{28} - [1](/page/1), with larger values encoded as doubles in network byte order; strings use a U29 length prefix followed by UTF-8 data, supporting up to $2^{28} - [1](/page/1) bytes.[2] Nesting in AMF3 remains recursive, but objects and arrays leverage reference tables to avoid duplication, encoding references as U29 indices into string, object, or traits tables.[2] Decoding in both AMF versions starts by reading the AMF version from the packet header (a 16-bit unsigned integer in network byte order) to determine compatibility, followed by sequential parsing of type markers and payloads.[1][2] Each marker dictates the payload length and format: for instance, after reading a number marker (0x00), 8 bytes are consumed directly as a double, while for objects, pairs are read until the end marker.[1] In AMF3, deserializers maintain three reference tables (for strings, objects, and traits) during parsing; a U29 with its high bit cleared signals a reference, which is resolved by indexing the appropriate table to reconstruct shared graph structures without re-encoding duplicates.[2] Incomplete payloads, such as truncated UTF-8 strings or unterminated objects, result in deserialization failures, often throwing exceptions like range errors for oversized U29 values or invalid markers.[1][2] Unsupported markers (e.g., 0x0D in AMF0) may be skipped or cause errors depending on the implementation, ensuring robust handling of legacy or mixed-version streams.[1]Usage and Legacy
Integration with Flash and RTMP
The Action Message Format (AMF) plays a central role in Flash Remoting, enabling remote procedure calls (RPC) between ActionScript applications and server-side services through the NetConnection class. In this context, AMF serializes method invocations, parameters, and responses into binary packets, allowing asynchronous communication over HTTP or RTMP protocols without requiring XML or JSON intermediaries. For instance, an ActionScript client can invoke a server method likegetUserData by passing the method name and arguments via NetConnection.call(), with AMF handling the encoding to preserve ActionScript types such as objects, arrays, and dates.[1][11]
In the Real-Time Messaging Protocol (RTMP), AMF serves as the payload format for command and metadata messages within chunked streams, facilitating real-time exchange in video and audio applications. AMF-encoded packets are embedded in RTMP messages with type 20 for AMF0 and type 17 for AMF3, allowing clients and servers to negotiate connections, control streams, and transmit descriptive data like stream metadata (e.g., duration, framerate). These messages are divided into chunks of configurable size (default 128 bytes) for efficient transmission over TCP, with each chunk header indicating the message type and payload offset.[12]
A key application involves media control commands, such as play and pause, where AMF encodes parameters like stream names, timestamps, and flags to manage playback in Flash-based players. For example, a "play" command might serialize a string stream identifier, a numeric start time, and a boolean reset flag into an AMF body, which the server acknowledges with a status response like NetStream.Play.Start; similarly, a "pause" command includes a timestamp and boolean to halt or resume the stream, ensuring synchronized audio/video delivery. This integration supports low-latency interactions in live streaming scenarios, with AMF's compact binary structure minimizing overhead compared to text-based alternatives.[12]
Flash Player implementations provide built-in AMF support starting with version 6, which introduced automatic serialization for AMF0 during NetConnection operations, ensuring compatibility for ActionScript 1.0 and 2.0 applications. From Flash Player 9 onward, AMF3 support was added alongside ActionScript 3.0, with negotiation occurring via a version header in AMF packets (e.g., using the avmplus-object-marker 0x11 to switch formats) and the ObjectEncoding property set to AMF3 for optimized encoding of complex objects. This backward compatibility allows seamless fallback to AMF0 if the server does not support AMF3, maintaining interoperability across Flash Player versions 6 through the final release.[1][2][13]