Skip to content

ESM / ESP Format

.esm (Elder Scrolls Master) and .esp (Elder Scrolls Plugin) files are Bethesda's binary record database format used across all modern Creation Engine games. In Fallout 4 they store every piece of game data: world geometry references, NPCs, items, quests, audio, weather, and more.

File Structure

An ESM is a flat binary stream of groups and records, each preceded by a 24-byte header.

Record Header (24 bytes)

Offset Type Meaning Notes
0x00 char[4] Type Record type code, e.g. "CELL", "NPC_", "TES4"
0x04 uint32 Data size Size of the field payload (excludes this header)
0x08 uint32 Flags See flags table below
0x0C uint32 Form ID Unique identifier within the plugin
0x10 uint16 Unknown Purpose is unknown
0x12 uint16 Unknown Purpose is unknown, but likely used for version control
0x14 uint16 Unknown Purpose is unknown
0x16 uint16 Unknown Purpose is unknown

Record flags:

Bit Meaning Notes
0x00000020 Deleted Record is logically removed; never spawns in-game. Vanilla Fallout4.esm contains none, but DLC and mod plugins can.
0x00000800 Initially Disabled Placed reference starts disabled. Visibility may be overridden by an XESP enable-parent chain.
0x00040000 Compressed Payload is zlib-compressed (see Compression below).
0x00800000 Marker Record is a CK-only marker object (XMarker, trigger box, etc.) that should not be rendered.

Note: some flags are context-dependent and have different meanings on different record types. The flags above are the ones confirmed through code analysis of Fallout 4. Older documentation sources (fopdoc, xEdit) list additional flags inherited from Skyrim's format, but several of those have been found to be incorrect for FO4.

GRUP Header (24 bytes)

Groups wrap records of the same type or records belonging to a parent record.

"GRUP"       char[4]   - magic
group_size   uint32    — total size including this header
label        char[4]   — record-type code for type=0; cell/world coords for others
group_type   int32     — see group type table
timestamp    uint16
vcs_info     uint16
unknown      uint32

Group types:

Value Meaning Label interpretation
0 Top-level Record type (e.g. CELL)
1 World children Worldspace form ID
2 Interior cell block Block number (int32)
3 Interior cell sub-block Sub-block number (int32)
4 Exterior cell block Grid Y (int16) + Grid X (int16)
5 Exterior cell sub-block Grid Y (int16) + Grid X (int16)
6 Cell children Cell form ID
7 Topic children Topic form ID
8 Cell persistent children Cell form ID
9 Cell temporary children Cell form ID

Field (Subrecord)

Within each record's decompressed payload, fields are packed end-to-end:

code    char[4]   — field type, e.g. "EDID", "DATA", "DNAM"
length  uint16    — byte length of data
data    byte[length]

XXXX override field: When a field named XXXX appears, its 4-byte payload contains a uint32 giving the true length of the immediately following field. That following field's own length uint16 is meaningless. This handles fields exceeding 65535 bytes.

Compression

When the record flag 0x00040000 is set, the record payload (after the 24-byte header) is:

uncompressed_size  uint32   — size after decompression
zlib_data          byte[]   — standard zlib stream (RFC 1950)

Decompress to uncompressed_size bytes, then parse fields normally.

TES4 — File Header Record

Always the first record. Key fields:

Field Type Content
HEDR struct Version (float32), num records (uint32), next object ID (uint32)
CNAM zstring Author name
SNAM zstring Description
MAST zstring Master filename (repeated per dependency)
DATA uint64 Master file size (paired with each MAST)

FormID / FormKey

Every record is identified by a 32-bit FormID. The upper 8 bits encode the load order index of the plugin that owns the record; the lower 24 bits are the record's local ID within that plugin.

When serialized as a string (FormKey): "0x{LocalID:X6}:{PluginFilename}", e.g. "0x03C0F0:Fallout4.esm".


World Hierarchy

Exterior world records are nested in a specific GRUP hierarchy:

GRUP(type=0, label="WRLD")         top-level worldspace group
  WRLD record                      worldspace metadata
  GRUP(type=1, label=wrld_formid)  world children
    CELL record                    persistent worldspace cell
    GRUP(type=4, label=blockXY)    exterior cell block
      GRUP(type=5, label=subXY)    exterior cell sub-block
        CELL record                individual exterior cell
        GRUP(type=6, label=cell)   cell children
          LAND record              landscape data
          REFR/ACHR/...            placed objects

Interior cells live under a different top-level group:

GRUP(type=0, label="CELL")
  GRUP(type=2, label=blockNum)     interior cell block
    GRUP(type=3, label=subNum)     interior cell sub-block
      CELL record
      GRUP(type=6, label=cell)
        REFR/ACHR/...

Record Types

ARMO — Armor

Field Type Content
EDID zstring Editor ID
FULL lstring Name
MODL zstring World model (male)
MOD2 zstring World model (female)
DNAM struct Armor rating (float32)
DATA struct Value (int32) + weight (float32)
BODT / BOD2 struct Body slot flags
RNAM formid Race
EITM formid Enchantment
INDX uint32 Addon index

CELL — Cell

Field Type Content
EDID zstring Editor ID
FULL lstring Display name
DATA uint16 Flags (interior=1, has water=2, etc.)
XCLC struct Grid X (int32), Grid Y (int32), Force hide land (uint32)
XCLL struct Lighting (ambient, directional, fog colors + distances)
LTMP formid Lighting template
XEZN formid Encounter zone
XCLW float32 Water height
XCWT formid Water type
XOWN formid Owner

CONT — Container

Field Type Content
EDID zstring Editor ID
FULL lstring Name
MODL zstring Model path
DATA struct Flags (uint8) + weight (float32)
SNAM formid Open sound
QNAM formid Close sound
CNTO struct Item entry: formid + int32 count (repeated)

DIAL / INFO — Dialogue

DIAL (topic) groups INFO (response) records.

DIAL field Content
EDID Editor ID
FULL Topic name
PNAM Priority (float32)
BNAM Branch (formid)
QNAM Quest (formid)
DATA Flags
INFO field Content
EDID Editor ID
TRDT Response data: emotion type (uint32), emotion value (uint32), unused, response number, unused, sound (formid), flags, unused
NAM1 Response text (lstring)
NAM2 Actor notes (lstring)
SNAM Speaker (formid)
PNAM Previous INFO (formid)
CNAM Conditions

FLST — Form List

Field Content
EDID Editor ID
LNAM FormID entry (repeated)

GMST — Game Setting

Field Content
EDID Editor ID; first character encodes type: i=int, f=float, s=string, b=bool
DATA Value, interpreted per type prefix

KYWD — Keyword

Field Content
EDID Editor ID
CNAM Color (RGBA uint32)

LAND — Landscape

Field Type Content
DATA uint32 Flags
VNML byte[3×33×33] Vertex normals (X, Y, Z bytes, one per vertex in 33×33 grid)
VHGT struct Height map: float32 offset + int8[33×33] deltas + 2 pad bytes
VCLR byte[3×33×33] Vertex colors (R, G, B, one per vertex)
BTXT struct Base layer: formid texture + uint8 quadrant + uint8 unknown + int16 layer
ATXT struct Alpha layer header: formid texture + uint8 quadrant + int16 layer
VTXT struct[] Alpha data for preceding ATXT layer (see below)

LAND vertex grid: 33×33 vertices per cell, covering a 4096-unit cell with one shared vertex per edge (adjacent cells share the border row/column).

Height reconstruction:

actual_height[row][col] = (offset + sum of deltas from [0][0] to [row][col]) * 8.0

Deltas accumulate along rows then columns.

VTXT format (Fallout 4 specific):

Each entry is 8 bytes:

position   uint16   — encodes row * 17 + col within a 17×17 quadrant sub-grid
unknown    uint16   — padding / unknown purpose
opacity    float32  — alpha value 0.0–1.0

Older games (Skyrim, Oblivion) used a 6-byte layout without the float opacity. FO4 switched to float precision and added the unknown uint16 padding.

Quadrants divide the cell into NW / NE / SW / SE. Each has its own 17×17 alpha grid.

LIGH — Light

Field Type Content
EDID zstring Editor ID
MODL zstring Model path
DATA struct Time (int32), radius (uint32), color (RGBA bytes), type flags (uint32), falloff exponent (float32), FOV (float32), near clip (float32), period (float32), intensity amplitude (float32), movement amplitude (float32)
FNAM float32 Fade value
SNAM formid Sound

LTEX — Landscape Texture

Field Type Content
EDID zstring Editor ID
TNAM formid Texture set (→ TXST)
MNAM formid Material type
HNAM struct uint8 friction + uint8 restitution
SNAM byte Specular exponent

NPC_ — Non-Player Character

Field Type Content
EDID zstring Editor ID
FULL lstring Name
RNAM formid Race
CNAM formid Class
VTCK formid Voice type
DNAM struct Skill values, health/stamina/AP offsets, level, calc min/max
ACBS struct Flags, magicka/stamina/health offsets, speed/disposition/aggression
SNAM struct Faction (formid) + rank (int8), repeated per faction
AIDT struct AI data: aggression, confidence, energy, responsibility, mood, assistance
PKID formid Package (repeated per package)
SPLO formid Spell (repeated per spell)
ITMO struct Inventory item: formid + int32 count
WNAM formid Default outfit
NAM5 uint16 Required AV for crime

QUST — Quest

Field Type Content
EDID zstring Editor ID
FULL lstring Name
DNAM struct Flags (uint16) + priority (uint8) + unknown (uint8) + quest type (uint32)
INDX uint32 Stage index marker
QSDT uint8 Stage flags
CNAM lstring Stage log text
QOBJ uint16 Objective index
NNAM lstring Objective description
ALID formid Alias ID

REFR — Placed Object Reference

Field Type Content
EDID zstring Editor ID (optional)
NAME formid Base object being placed
DATA struct Position (3× float32) + Rotation (3× float32, radians)
XSCL float32 Scale (default 1.0 if absent)
XOWN formid Owner
XLCK int32 Lock level
XTEL struct Teleport destination (door links)
XESP struct Enable state parent

SNDR — Sound Descriptor

Field Type Content
EDID zstring Editor ID
CNAM formid Sound category
SNAM formid Output model
FNAM struct Flags
LNAM uint32 Loop info
BNAM uint32 Echo time
GNAM uint32 Loop and frequency offset
HNAM struct Unknown
CS3P struct Sound file + params (repeated per alternate)

STAT — Static Object

Field Type Content
EDID zstring Editor ID
MODL zstring Model path
DNAM struct Max angle (float32) + Material (formid)
MNAM int32 Unknown

TES4 — File Header

(see above)

TXST — Texture Set

Field Type Content
EDID zstring Editor ID
TX00 zstring Diffuse
TX01 zstring Normal / gloss
TX02 zstring Environment mask / subsurface tint
TX03 zstring Glow / detail map
TX04 zstring Height / parallax
TX05 zstring Environment
TX06 zstring Multilayer / Inner layer
TX07 zstring Specular / backlight
DODT struct Decal data
DNAM uint16 Flags

WEAP — Weapon

Field Type Content
EDID zstring Editor ID
FULL lstring Name
MODL zstring Model path
DNAM struct Animation type, speed, reach, sight FOV, base damage, attack shots/sec, reload time
DATA struct Value (int32), weight (float32)
EITM formid Enchantment
EAMT uint16 Enchantment amount
INAM formid Impact dataset
WNAM formid First person model

WRLD — Worldspace

Field Type Content
EDID zstring Editor ID
FULL lstring Display name
WNAM formid Parent worldspace
PNAM struct Flags + unknown
MNAM struct Map data (width, height, NW cell coords, SE cell coords)
DATA uint8 Flags
NAM0 formid Low-level LOD
NAMA float32 Distant LOD mult

WTHR — Weather

Field Type Content
EDID zstring Editor ID
DNAM struct Fog distances near/far (day + night)
CNAM struct Sky upper/lower colors at dawn/day/dusk/night
NAM0 struct Ambient colors
NAM1 struct Directional colors
MNAM struct Fog colors
NNAM struct Fog colors near/far
PNAM struct Precipitation chance
ONAM formid Precipitation
GNAM formid Visual effect
DATA struct Wind speed, cloud speed, transDelta, sunGlare, sunDamage
SNAM struct Sound entry: formid + type (uint32) (repeated)

String Encoding

All text fields use one of two encodings:

  • zstring — null-terminated UTF-8, embedded directly in the field
  • lstring — either a null-terminated UTF-8 string (in non-localized plugins), or a uint32 string table index (when the plugin has the localization flag set in TES4). String tables live in .STRINGS, .DLSTRINGS, and .ILSTRINGS sidecar files.

FormID Remapping

When a record from plugin B references a record from plugin A, the upper 8 bits of the stored FormID encode B's load-order index for A — not A's actual load order. Resolving references requires looking up the correct master in the TES4 MAST list.