A MOBI file is a Palm OS database (PDB), the container Palm handhelds used for applications’ data. The file starts with a 78-byte header, then a list with one 8-byte entry per record, then the records themselves. Each record is a block of bytes that runs from its own offset to the next record’s offset, or to the end of the file for the last one. All numbers are big-endian. Mobipocket never published a specification; this page follows the public reverse-engineering work listed on the overview.
Database header
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
0 | 32 | char[32] | name | The database name, ended by a zero byte and padded with zeros: at most 31 characters. Palm OS used it as the file’s name on the device. Mobipocket tools put a shortened title here, with spaces often turned into underscores; the full title is in record 0. |
32 | 2 | UInt16 | attributes | Database flags: see attributes. Usually 0 in ebooks. |
34 | 2 | UInt16 | version | The application’s own version number for the database. Usually 0. |
36 | 4 | UInt32 | creationDate | When the database was created, in seconds: see dates. |
40 | 4 | UInt32 | modificationDate | When it was last changed. |
44 | 4 | UInt32 | lastBackupDate | When it was last backed up by a HotSync. Often 0. |
48 | 4 | UInt32 | modificationNumber | A counter Palm OS raised on each change. Usually 0. |
52 | 4 | UInt32 | appInfoID | Offset of an application info block, or 0 for none. 0 in MOBI files. |
56 | 4 | UInt32 | sortInfoID | Offset of a sort info block, or 0 for none. 0 in MOBI files. |
60 | 4 | char[4] | type | The database type: BOOK for a Mobipocket or Kindle book. See type and creator. |
64 | 4 | char[4] | creator | The creator: MOBI. Palm OS opened the database with the application registered for this code. |
68 | 4 | UInt32 | uniqueIDSeed | Used by Palm OS to give new records unique IDs. Writers commonly store twice the number of records minus 1, or 0; readers ignore it. |
72 | 4 | UInt32 | nextRecordListID | Used only in memory on the device; 0 in a file. |
76 | 2 | UInt16 | numRecords | The number of records, N. |
Attributes
| Bit | Value | Meaning |
|---|---|---|
| 0 | 0x0001 | Resource database (a .prc application, not a record database). Not set in books. |
| 1 | 0x0002 | Read-only. |
| 2 | 0x0004 | The application info block has changed (dirty). |
| 3 | 0x0008 | Back this database up at the next HotSync, when no conduit handles it. |
| 4 | 0x0010 | A newer copy may be installed over this one while it is open. |
| 5 | 0x0020 | Reset the device after installing. |
| 6 | 0x0040 | Do not allow the database to be beamed or copied to another device. |
| 7 | 0x0080 | File stream database (Palm OS 3.0 and later). |
| 8 | 0x0100 | Hidden from the launcher. |
| 9 | 0x0200 | Launchable data: the launcher may open it with its creator application. |
| 15 | 0x8000 | The database was open when it was copied; set only on the device. |
These are Palm OS’s meanings; Mobipocket readers ignore the field. Other bits are unused in book files.
Dates
Palm OS counts seconds from 1 January 1904 as an unsigned 32-bit number, which runs
out in 2040. Some tools that build MOBI files, starting with the Perl
Palm::PDB module, instead write seconds from 1 January 1970, the Unix
epoch, as a signed number. A reader can tell them apart from the top bit: when it is
set, the value counts from 1904 (any date after 1972 has it set); when it is clear, it
counts from 1970, since a 1904 value without the top bit would fall before the format
existed.
Type and creator
The type and creator codes at offsets 60 and 64 tell a reader what the database
holds. A file named .mobi, .prc or .azw may be
any of the Palm ebook formats below, so a reader should check these eight bytes rather
than the extension.
| Type | Creator | Format |
|---|---|---|
BOOK | MOBI | Mobipocket book, including Kindle MOBI, AZW and AZW3 files |
TEXt | REAd | PalmDOC: plain text with the same 16-byte header in record 0 but no MOBI header. Mobipocket Reader opens these too. |
TEXt | TlDc | TealDoc, a PalmDOC variant |
PNRd or Data | PPrs | eReader (Peanut Press), a different format |
Data | Plkr | Plucker, a different format |
ToGo | ToGo | iSilo, a different format |
SDoc | SilX | iSilo 3, a different format |
zTXT | GPlm | Weasel Reader’s zTXT, a different format |
Record list
The record list starts at offset 78 and has N entries of 8 bytes.
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
0 | 4 | UInt32 | offset | Where the record starts, from the start of the file. Offsets must rise from one entry to the next. |
4 | 1 | UInt8 | attributes | The record’s flags: see below. Usually 0. |
5 | 3 | UInt24 | uniqueID | The record’s ID. In MOBI files it is normally twice the record number (0, 2, 4…); readers do not depend on it. |
| Bits | Value | Meaning |
|---|---|---|
| 0–3 | 0x0F mask | Category, 0 to 15; 0 means unfiled. |
| 4 | 0x10 | Secret (private) record. |
| 5 | 0x20 | Busy: in use by an application. |
| 6 | 0x40 | Dirty: changed since the last HotSync. |
| 7 | 0x80 | Delete at the next HotSync. |
After the list come two zero bytes of padding, written by Palm OS tools and kept by Mobipocket’s, so record 0 usually starts at 78 + 8N + 2.
Order of the records in a MOBI file
The PDB container does not give records types; the MOBI header in record 0 says which record holds what. A typical book made by Mobipocket Creator or KindleGen has them in this order:
- Record 0: the PalmDOC header, MOBI header, EXTH metadata and the full title.
- The text records, from 1 to the PalmDOC header’s record count, each holding up to 4,096 bytes of text once uncompressed.
- Sometimes a padding record of zero bytes.
- Index records (
INDX), for the table of contents or a dictionary. - Images, one per record, from the MOBI header’s first image record onwards; cover and thumbnail are found through EXTH 201 and 202.
- HUFF and CDIC records, when the text uses Huffman compression.
FLIS,FCIS,SRCSand other tagged records.- The end-of-file record,
E9 8E 0D 0A.
Example
The start of a book with 251 records, made by KindleGen.
00000000 54 68 65 5F 54 69 6D 65 5F 4D 61 63 68 69 6E 65 The_Time_Machine
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000020 00 00 00 00 4F 9A 2B 1C 4F 9A 2B 1C 00 00 00 00 ....O.+.O.+.....
00000030 00 00 00 00 00 00 00 00 00 00 00 00 42 4F 4F 4B ............BOOK
00000040 4D 4F 42 49 00 00 01 F5 00 00 00 00 00 FB 00 00 MOBI............
00000050 07 F8 00 00 00 00 00 00 0A 48 00 00 00 02 ... .........H....
| Bytes | Field | Value |
|---|---|---|
54 68 … 65 00 … | name | The_Time_Machine |
00 00, 00 00 | attributes, version | 0, 0 |
4F 9A 2B 1C | creationDate | top bit clear, so seconds since 1970: 27 April 2012 |
42 4F 4F 4B, 4D 4F 42 49 | type, creator | BOOK, MOBI |
00 00 01 F5 | uniqueIDSeed | 501 = 2 × 251 − 1 |
00 FB | numRecords | 251 |
00 00 07 F8, 00, 00 00 00 | record 0 | starts at 2,040 = 78 + 8 × 251 + 2; ID 0 |
00 00 0A 48, 00, 00 00 02 | record 1 | starts at 2,632; ID 2 |
The example is built to show the layout; its dates and offsets are illustrative.