The format is defined by the OpenStreetMap wiki page
“PBF Format” (read
2026-11-12) and two
Protocol Buffers files,
fileformat.proto and osmformat.proto, from the OSM-binary
project. The number before each field is its Protocol Buffers field number.
Blocks
- 4 bytes, big-endian: length of the BlobHeader. At most 64 KiB.
- The
BlobHeadermessage. - The
Blobmessage,datasizebytes long. At most 32 MiB, and should be under 16 MiB.
| Message | Fields |
|---|---|
BlobHeader | 1 type (string, required): OSMHeader or OSMData; 2 indexdata (bytes, for indexes); 3 datasize (int32, required). |
Blob | 2 raw_size (int32): size when uncompressed. One of: 1 raw, 3 zlib_data, 4 lzma_data, 5 OBSOLETE_bzip2_data, 6 lz4_data, 7 zstd_data. |
All readers and writers must support uncompressed and zlib data; the other
compressions are optional and not widely used. An OSMHeader block must
come before the first OSMData block, and parsers skip block types they
do not recognise.
HeaderBlock
| Field | Meaning |
|---|---|
1 bbox | HeaderBBox: 1 left, 2 right, 3 top, 4 bottom, sint64 (the wiki does not state the unit). |
4 required_features | Strings a reader must understand: OsmSchema-V0.6, DenseNodes, HistoricalInformation (file holds old versions). |
5 optional_features | Hints: Has_Metadata, Sort.Type_then_ID, Sort.Geographic, timestamp=…, LocationsOnWays. |
16 writingprogram | The program that wrote the file. |
17 source | Source of the data (“From the bbox field”, says the wiki’s comment). |
32 osmosis_replication_timestamp | Replication timestamp, in seconds since the epoch. |
33 osmosis_replication_sequence_number | Replication sequence number (sequenceNumber in Osmosis’s state.txt). |
34 osmosis_replication_base_url | Replication base URL (from Osmosis’s configuration.txt). |
PrimitiveBlock
| Field | Meaning |
|---|---|
1 stringtable | StringTable: 1 s, repeated bytes. Entry 0 is empty and used as a separator; keys, values, user names and roles refer to entries by index. |
2 primitivegroup | Repeated. Each group holds one kind only: 1 nodes, 2 dense, 3 ways, 4 relations or 5 changesets. |
17 granularity | Nanodegrees per coordinate unit; default 100. |
19 lat_offset, 20 lon_offset | Nanodegrees added to every coordinate; default 0. |
18 date_granularity | Milliseconds per timestamp unit; default 1000. |
Latitude in degrees = 10−9 × (lat_offset +
granularity × lat), and the same for longitude.
Elements
| Message | Fields |
|---|---|
Node | 1 id (sint64), 2 keys, 3 vals (packed uint32 string indexes), 4 info, 8 lat, 9 lon (sint64). |
DenseNodes | 1 id (packed sint64, delta-coded), 5 denseinfo, 8 lat, 9 lon (packed sint64, delta-coded), 10 keys_vals (packed int32: key, value pairs for each node, each node ending with 0). |
Way | 1 id (int64), 2 keys, 3 vals, 4 info, 8 refs (packed sint64 node IDs, delta-coded), 9 lat, 10 lon (delta-coded node positions, with LocationsOnWays). |
Relation | 1 id, 2 keys, 3 vals, 4 info, 8 roles_sid (packed int32 string indexes), 9 memids (packed sint64, delta-coded), 10 types (packed MemberType: 0 NODE, 1 WAY, 2 RELATION). |
ChangeSet | Allowed in a group (field 5), but the wiki gives no fields for it. |
Metadata
| Message | Fields |
|---|---|
Info | 1 version (int32, default −1), 2 timestamp (int64, in date-granularity units), 3 changeset, 4 uid, 5 user_sid (string index), 6 visible (history data: requires the HistoricalInformation feature; absent means true, false means deleted). |
DenseInfo | The same fields as packed arrays, one entry per node: 1 version, then delta-coded 2 timestamp, 3 changeset, 4 uid, 5 user_sid; 6 visible. |
Delta coding: the first value is stored as it is, each later one as the difference
from the one before, all zigzag-encoded (sint64).