W3docs

unpack()

In this article, we will focus on the PHP unpack() function. We will provide you with an overview of the function, how it works, and examples of its use.

PHP strings are really just sequences of raw bytes, which makes them a natural container for binary data — image headers, network packets, file formats, and protocol frames. The unpack() function reads that raw byte stream and turns it into ordinary PHP values (integers, floats, strings) you can work with. This article covers the function's signature, its format codes, endianness, common gotchas, and how it pairs with pack().

Syntax

unpack(string $format, string $data, int $offset = 0): array|false
ParameterDescription
$formatA format string describing how to interpret the bytes (codes are listed below).
$dataThe binary string to read from.
$offsetByte position to start reading from (added in PHP 7.1). Defaults to 0.

It returns an associative array of the unpacked values, or false on failure. unpack() is the inverse of pack(): whatever layout you write with pack() you read back with the same format codes.

A first example

The format string is a sequence of one or more codes. Each code is a single letter for a data type, an optional repeat count, and an optional name.

php— editable, runs on the server

Here "C*" means "read every remaining byte as an unsigned 8-bit integer". The * repeat count consumes all available bytes. When you don't supply a name, unpack() numbers the results starting at 1 (not 0):

Array
(
    [1] => 1
    [2] => 2
    [3] => 3
    [4] => 4
    [5] => 5
)

Format codes

Each code maps to a fixed number of bytes. The most common ones:

CodeTypeSize
C / cUnsigned / signed char1 byte
nUnsigned short, big-endian2 bytes
vUnsigned short, little-endian2 bytes
S / sUnsigned / signed short, machine byte order2 bytes
NUnsigned long, big-endian4 bytes
VUnsigned long, little-endian4 bytes
L / lUnsigned / signed long, machine byte order4 bytes
f / dFloat / double, machine order4 / 8 bytes
a / AString (NUL-padded / space-padded)as specified
H / hHex string, high / low nibble firstper nibble

A number after a code repeats it (C4 reads four chars); a * reads all remaining bytes.

Naming the fields

Real binary formats are made of mixed fields, so you usually give each one a name and separate the codes with /:

php— editable, runs on the server

"C2chars/Sint/Nlong" reads the first two bytes as chars1/chars2, the next two as a machine-order short int, and the last four as a big-endian long long:

Array
(
    [chars1] => 1
    [chars2] => 2
    [int] => 1027
    [long] => 84281096
)

When a code has a repeat count and a name, unpack() appends an index to the name (chars1, chars2, …) so the values don't collide.

Endianness matters

The same four bytes mean different numbers depending on byte order. N/n are big-endian (network order); V/v are little-endian (x86 native); S/L follow the host machine and are therefore not portable. For data that crosses machines — a file format or a network protocol — always pick an explicit-endian code so the result is the same everywhere.

<?php
$bytes = "\x01\x00\x00\x00";
print_r(unpack("Vlittle", $bytes)); // little-endian: 1
print_r(unpack("Nbig", $bytes));    // big-endian: 16777216
?>
Array
(
    [little] => 1
)
Array
(
    [big] => 16777216
)

Round-tripping with pack()

Because unpack() is the mirror image of pack(), you can serialize values to a compact binary blob and read them straight back with the matching format:

<?php
$packed = pack("nN", 1027, 84281096); // build the bytes
$result = unpack("nshort/Nlong", $packed);
print_r($result);
?>
Array
(
    [short] => 1027
    [long] => 84281096
)

Common gotchas

  • Keys start at 1. Unnamed results are 1-indexed, which trips people up when looping. Name your fields or remember the offset.
  • Names with repeat counts get an index suffix (byte1, byte2), so unpack("C4byte", ...) yields byte1byte4, not one byte.
  • Machine-order codes (S, L, s, l) aren't portable. Use n/N or v/V for anything stored or transmitted.
  • false on too-little data. If the format demands more bytes than $data holds, unpack() returns false and emits a warning — check the return value before using it.

Conclusion

The unpack() function turns raw bytes into PHP values using compact format codes, and is the reading half of the pack() pair. Master the endianness codes and the field-naming syntax and you can parse virtually any binary file header or network frame. For converting binary to a readable hex string instead, see bin2hex().

Practice

Practice
What does the PHP 'unpack' function do?
What does the PHP 'unpack' function do?
Was this page helpful?