Cell & Shape

WKB Format Explained, Byte by Byte

WKB (Well-Known Binary) looks like an inscrutable wall of hex — but it has a simple, strict structure. Paste any WKB or EWKB hex below and this tool walks it one field at a time: the byte-order flag, the geometry-type integer, an optional SRID, the ring and point counts, and every coordinate double — each colour-coded, with its decoded value beside it and the geometry drawn on a map. It all runs in your browser; nothing you paste is uploaded.

What WKB actually is

WKB is the binary serialization of the OGC Simple Features geometry model — the same conceptual geometry as WKT (POINT, LINESTRING, POLYGON, and their MULTI* forms), but written as raw bytes instead of text. Databases and geometry libraries prefer it because bytes are faster to read and more compact than parsing a text grammar: PostGIS, GEOS, JTS, Shapely, and most spatial stores speak WKB internally and hand it to you as a hex string.

Every WKB geometry follows the same three-part opening, then a body that depends on the type:

  1. 1 byte Byte order 00 = big-endian, 01 = little-endian
  2. 4 bytes Geometry type uint32: 1 Point, 2 LineString, 3 Polygon, 46 Multi*
  3. 4 bytes SRID (EWKB only) present when the type’s 0x20000000 flag bit is set
  4. 4 bytes each Counts ring count, then a point count per ring (Polygon); point count (LineString)
  5. 8 bytes each Coordinates IEEE-754 doubles, X (lon) then Y (lat), repeated per vertex

A bare 2D point is the smallest complete example: 01 (little-endian) + 01000000 (type 1 = Point) + eight bytes of longitude + eight bytes of latitude. That is exactly the default example loaded above — POINT(-73.9857 40.7484), the Empire State Building.

Endianness: why the first byte matters

The opening byte is not part of the geometry — it is an instruction for reading everything after it. Little-endian (01, “NDR”) stores each multi-byte number least-significant byte first, which is what Intel and ARM CPUs and virtually every database use. Big-endian (00, “XDR”) stores most-significant byte first, the classic network byte order.

The practical consequence: the same coordinate has two different byte strings. The longitude -73.9857 is b3ea73b5157f52c0 little-endian and c0527f15b573eab3 big-endian — the exact reverse, byte for byte. Read a little-endian value as big-endian and you get garbage coordinates in the middle of the ocean. Because each nested geometry inside a MULTI* or GEOMETRYCOLLECTION carries its own flag byte, one WKB value can legally mix both orders; well-behaved encoders never do, but a robust reader must honour each byte.

WKB vs EWKB vs TWKB

Three encodings share the “WKB” name; they solve different problems.

OGC WKB

The standard. Byte order, type, geometry — no coordinate reference system is carried, and higher dimensions are signalled by adding to the type code (1001 = PointZ, 2001 = PointM, 3001 = PointZM). This is what ST_AsBinary() produces and what the OGC spec defines.

EWKB (Extended WKB)

PostGIS’s superset. Instead of the thousands-digit convention, EWKB steals the high bits of the 32-bit type field as flags: 0x20000000 means a 4-byte SRID follows the type, 0x80000000 means the coordinates carry a Z, and 0x40000000 means they carry an M. So an EWKB point in WGS84 encodes its type as 0x20000001 and inserts the SRID (0x000010E6 = 4326) before the coordinates. Paste the “EWKB + SRID” example above to watch the annotator surface that extra field. ST_AsEWKB() emits this form.

TWKB (Tiny WKB)

A transport-optimised cousin. TWKB throws out fixed 8-byte doubles in favour of delta-encoded, quantized integers packed as variable-length varints, with a configurable number of decimals. Geometries shrink several-fold, at the cost of some precision and all human-readability. Use WKB/EWKB for storage and exact round-trips; use TWKB when you are moving many geometries over the wire.

The hex tax

WKB is binary, but binary rarely survives a SQL console, a JSON payload, or a web page — so it is almost always handed to you as hexadecimal, where every byte becomes two characters. That is a flat 2× size penalty before you have encoded a single coordinate, and each 2D vertex already costs 16 bytes (two doubles) → 32 hex characters. It is why a modest polygon’s WKB hex runs to hundreds of characters.

If size is what brought you here, the geometry format size comparison guide measures WKB hex against WKT, GeoJSON, and TWKB on real geometries — including how much the hex envelope and the fixed-width doubles cost you versus TWKB’s varints.

PostGIS snippets

The functions you need to move between WKB, EWKB, and the human formats:

-- Geometry → WKB (OGC, hex) and → EWKB (PostGIS, hex)
SELECT ST_AsBinary(geom)  AS wkb_hex   FROM features;   -- no SRID
SELECT ST_AsEWKB(geom)    AS ewkb_hex  FROM features;   -- SRID embedded

-- WKB/EWKB → geometry
SELECT ST_GeomFromWKB(decode('0101000000b3ea73b5157f52c0c7293a92cb5f4440', 'hex'), 4326);
SELECT ST_GeomFromEWKB(decode('0101000020e6100000b3ea73b5157f52c0c7293a92cb5f4440', 'hex'));

-- Inspect without decoding by hand
SELECT ST_GeometryType(geom), ST_SRID(geom), ST_AsText(geom) FROM features;

Casting a geometry to bytea in psql already shows you the EWKB hex — the \x-prefixed string you see in a raw SELECT geom is EWKB. Paste that (with or without the 0x) straight into the decoder above.

Decoding WKB in code

Every mainstream geometry stack ships a WKB reader, so you should almost never hand-roll one:

The annotator on this page hand-walks the bytes only to explain them; for the actual geometry and the map it uses the same engine as the universal geometry inspector, so what you see rendered is a real parse, not a best guess.

Sources and further reading

The byte layout and database examples above are checked against the standards publisher and current PostGIS reference documentation.

Frequently asked questions

What is WKB?
WKB (Well-Known Binary) is the binary serialization of the OGC Simple Features geometry model — the same geometry model as WKT, but encoded as raw bytes instead of text. A WKB value starts with a one-byte endianness flag, then a 32-bit geometry-type code, then the geometry’s coordinates as IEEE-754 doubles. It is what PostGIS, GEOS, Shapely, JTS, and most spatial databases store and exchange internally, because parsing bytes is faster and more compact than parsing text.
How do I decode a WKB hex string?
Paste it into the tool above. It walks the hex byte by byte: the first byte (00 or 01) is the byte order, the next four bytes are the geometry type, then come the ring/point counts and the coordinate doubles. Each field is colour-coded with its decoded value beside it, and the parsed geometry is drawn on the map — all in your browser, nothing uploaded. In code, use ST_GeomFromWKB in PostGIS, shapely.wkb.loads in Python, or a WKB reader such as wkx in JavaScript.
What is the difference between WKB and EWKB?
EWKB (Extended WKB) is PostGIS’s superset of OGC WKB. It reuses the high bits of the 32-bit geometry-type field as flags: 0x20000000 means a 4-byte SRID follows the type, 0x80000000 means the coordinates carry a Z value, and 0x40000000 means they carry an M value. So an EWKB point with SRID 4326 encodes the type as 0x20000001 and inserts the SRID (0x000010E6 = 4326) before the coordinates. Plain OGC WKB has no SRID and encodes higher dimensions with the thousands digit instead (1001 = PointZ). ST_AsBinary emits OGC WKB; ST_AsEWKB emits EWKB.
Why is WKB stored as hex?
WKB is genuinely binary, but binary does not survive being pasted into a SQL console, a JSON field, or a web page. Hexadecimal is the usual text-safe envelope: every byte becomes two hex characters, so the encoding doubles in size versus the raw bytes. That “hex tax” is why a WKB hex string looks so long — see the size-comparison guide for measured numbers against WKT, GeoJSON, and TWKB.
What is TWKB and how is it different from WKB?
TWKB (Tiny WKB) is a compact variant designed for transport. It drops the fixed 8-byte doubles in favour of delta-encoded, quantized integers with variable-length (varint) packing, and it lets you choose how many decimal places to keep. The result is often several times smaller than WKB, at the cost of a little precision and human-readability. Use WKB/EWKB for database storage and exact round-trips; reach for TWKB when you are shipping many geometries over the wire.
What does the byte-order flag mean?
The first byte of every WKB geometry says how the multi-byte numbers that follow are laid out: 01 is little-endian (NDR, least-significant byte first — what Intel/ARM and most databases use) and 00 is big-endian (XDR, most-significant byte first). Every uint32 count and every 8-byte double after the flag is read in that order. Nested geometries inside a MultiPolygon or GeometryCollection each carry their own byte-order byte, so a single value can technically mix both.