What Is a PST File? The Outlook Data File Microsoft Made, and How to Check, Fix and Convert One
A PST file is an Outlook data file that stores mail, contacts, calendar items and tasks in one file. Three readers gave one answer on 16 of the 21 damaged copies we made of one. Jump to your question below, or work through it in order.
What Is a PST File? The Outlook file that stores mail, contacts and more
Short answer
A PST file is an Outlook data file that stores mail, contacts, calendar items and tasks in one file. Microsoft made the format, and it is also called a Personal Storage Table. A PST file starts with the four characters !BDN.
We tested 32 public PST and OST files with three readers, libpff, pst-extractor and readpst. 28 files opened in all three. We then damaged one PST file in 21 ways, and the three readers gave one answer on 16 copies.
To open one, see the open steps. To check one, see the check steps. If your PST file will not open, begin with the eight causes.
A PST file is an Outlook data file. It stores mail, contacts, calendar items and tasks in one file on your computer. Microsoft made the format, and the full name is Personal Storage Table.
Picture a work laptop with an old mail archive named archive. Outlook opens it and shows ten years of mail. Picture a second file with the same ending that every tool refuses. The ending is the same, and only the bytes inside show which one is sound.
Microsoft Support says a PST file stores items like mail, contacts, appointments, tasks, notes and journal entries. People use it to back up messages or to keep older items on their computer so the mailbox stays small.
Wikipedia says the format is used by Exchange Client, Windows Messaging and Outlook. Outlook 2002 and earlier wrote the older ANSI form, with a 2 GiB limit. Outlook 2003 brought the Unicode form with 64 bit pointers and room for larger files.
A PST file is a message store. Microsoft's format specification calls it a tree of folders. Folders contain messages, and messages contain attachments. Properties on those objects store all the facts about every item.
Microsoft publishes that specification as MS-PST. Its own revision list gives 18 February 2025 as the latest release, and Wikipedia says it falls under the Open Specification Promise. That is why free readers like libpff can open the file without Outlook.
Where our PST files come from
We read 32 unique files from 4 public projects. Aspose.Email gives 23, pst-extractor gives 4, java-libpst gives 3 and Apache Tika gives 2. We dropped copies with the same SHA-256 hash.
They are test files from code projects. They are 271,360 to 16,818,176 bytes long and 128,454,656 bytes in total, and the median is 271,360 bytes. 25 end in .pst and 7 end in .ost. We also damaged one file of 271,360 bytes in 21 ways.
So this page studies how readers treat the PST layout, and not a sample of everyday mail archives. The files contain sample mail, contacts and calendar items. We opened nothing in Outlook, so we make no claim about what Outlook accepts.
PST file facts at a glance
| Property | Value |
|---|---|
| Meaning | Personal Storage Table. It stores mail, contacts, calendar items and tasks. |
| Ending | .pst. The twin file made for cached mail ends in .ost. |
| Maker | Microsoft. Outlook 2003 added the Unicode form, per Wikipedia. |
| Layout | A header of 564 bytes, then pages that form trees of nodes and blocks, per MS-PST. |
| Kinds | Unicode version 23, Unicode with 4 KB pages version 36 and older ANSI. 28, 4 and 0 of our 32 files. |
| Size limit | Outlook 2010 to 2016 stop at 50 GB by default, per Microsoft Learn. |
| First bytes | !BDN, then a checksum and the letters SM. Our example says SM and version 23. |
| Our tests | 32 files, 21 damaged copies, 3 readers, 1 header repair route and a script of 24 lines. |
Wrong page? An EML file is one message, and an MBOX file is many messages as text. See how PST files differ from OST, MSG and EML.
Which Kind of PST File Do You Have? Three kinds, and the version names the kind
Three kinds name the build of an Outlook data file. Our 32 files include 28 of the Unicode kind with version 23 and 4 with version 36. We found no older ANSI file. The ending says little, because 2 files named .ost show the PST letters SM.
Read byte 10 for the version and bytes 8 and 9 for the letters, and follow the figure. We tested the first two kinds with three readers. We have no ANSI file, so the third row comes from the specification and not from our tests.
The three kinds in detail
| Kind | Files and results |
|---|---|
| Unicode, version 23 | 28 files. The file stores text as Unicode with 64 bit pointers and pages of 512 bytes. All three readers opened 24 of them. 25 end in .pst and 3 in .ost. |
| Unicode, version 36 | 4 files. The pages are 4,096 bytes and the data is not encoded. All 4 end in .ost and show the letters SO. All three readers opened all 4. |
| ANSI, version 14 or 15 | 0 files. The MS-PST version list gives versions 14 and 15 to the ANSI form. Microsoft says it stops near 2 GB. We tested none, so we make no claim about readers. |
Start with the first bytes
Open the file in a hex viewer, or use xxd -l 32 example.pst on Linux or Mac. Our file starts with 21 42 44 4e, the characters !BDN. Then come four bytes of checksum, the letters SM and the version 23.
xxd -l 32 example.pst
00000000: 2142 444e 8f38 3f3d 534d 1700 1300 0101 !BDN.8?=SM......
00000010: 0000 0000 0000 0000 0000 0000 0000 0000 ................
file -b example.pst | fold -s -w 76
Microsoft Outlook Personal Storage (>=2003, Unicode, version 23),
bidUnused=0000000000000000, dwUnique=0x54, 271360 bytes, bCryptMethod=1,
CRC32 0x99d7521e
The file command read the bytes and not the ending. It named the file an Outlook Personal Storage and printed the version. We used it on our example only, so we make no claim about its answers on the other files.
The letters in bytes 8 and 9 separate the twins. The MS-PST header list lists only SM. Our 27 PST style files say SM, and our 5 OST style files say SO. All 5 SO files end in .ost.
Not sure your file is a PST file at all? Check it with our script.
What Is Inside a PST File? A header, pages and two trees
A PST file is a header of 564 bytes followed by pages. Our example is 271,360 bytes long. The header has two checksums, the size of the file and a pointer to both trees, and the readers use all of them.
We looked inside a PST file because its layout explains every result later on this page. Our example contains four mails and comes from the Apache Tika test files. The start shows the header, and the rest is pages of 512 bytes.
xxd -l 32 example.pst
00000000: 2142 444e 8f38 3f3d 534d 1700 1300 0101 !BDN.8?=SM......
00000010: 0000 0000 0000 0000 0000 0000 0000 0000 ................
The MS-PST header page lists the fields in order. The Unicode header has a magic value, a partial checksum, the version, a root of 72 bytes, a byte that names the encoding and a full checksum. Added up, it is 564 bytes.
The parts, one by one
The partial checksum covers 471 bytes that start at byte 8, and the full checksum covers 516 bytes that start there. Both matched in 31 of our 32 files. The size field at byte 184 matched the actual file size in all 32.
The root has two pointers. In our example one leads to the node tree at byte 49,152, and the other leads to the block tree at byte 38,912. Every page ends with a trailer, and its type byte is 0x81 for the node tree and 0x80 for the block tree.
What every part stores
| Part | What it stores |
|---|---|
| Magic | The characters !BDN. Copy A6 zeroes them, and all three readers refused it. Copy A5 adds 16 bytes in front, and all three refused that too. |
| Checksums | Two values in the header. Copy B4 flips one bit and keeps the old checksum. libpff refused it, and the other two read it. |
| File size | The size in bytes, at byte 184. Copy B5 sets it to 0 and re-signs the checksums. libpff refused it, and the other two read it. |
| Encoding byte | Says whether the data is encoded, at byte 513. Copy B2 sets 0 where the file has 1. Only libpff read the file, and its answer matched the original. |
| Node tree | Maps every folder and message to its data. Copy C6 zeroes its root page, and all three readers refused it. |
| Block tree | Maps every block to its place in the file. Copy C7 zeroes its root page, and all three readers refused it. |
| Data blocks | The text of the mails. Copy C2 zeroes 64 bytes, and all three readers still returned the four mails. |
What the sources say
Wikipedia describes the encoding choices. Microsoft offers three settings, none, a compressible form with a fixed byte table and a high form. Neither uses your password in its code. Our 28 files with version 23 show the value 1, the permutation form in MS-PST, and the 4 others show 0, which means no encoding.
We read the layout from our own files and from the Microsoft page. We did not read the rest of MS-PST, so we make no claim about rules outside the header.
The map is small. Our script checks the magic, the version, two checksums and the file size. It cannot see inside a page, so a damaged page can pass it, as the 21 copies show.
What Did We Find in 32 Test PST and OST Files? Three readers, and one file beat all of them
We read 32 public PST and OST files with three readers and a 24 line script. 28 files opened in all three. 1 file failed in all three, and 3 files split the readers. The script flagged the one file that all three refused.
All 32 files come from 4 public projects, so this is a study of those projects and not of mail archives in general. A pass means that the reader opened the file and walked every folder and message without an error. A pass for readpst means exit code 0.
Readers were libpff 20260926 through pypff, pst-extractor 1.12.0 and readpst 0.6.76, all on Linux. We tested every file alone, in a fresh folder. libpff and readpst come from different projects. pst-extractor says it is based on java-libpst, and the java-libpst readme says it started from the libpff file notes, so those answers are not fully independent.
| Test | Result |
|---|---|
| libpff 20260926 | Opened 28 of 32 files through its Python binding pypff. It refused the 4 files that split or stopped the readers. |
| pst-extractor 1.12.0 | Opened 30 files. It is written in TypeScript. It counted far fewer items than libpff in the 3 largest OST files. |
| readpst 0.6.76 | Opened 31 files, the most of the three. It is part of libpst and writes MBOX files. It refused only the file with the bad checksum. |
| Our script | Printed OK for 31 files and FLAG for 1. It printed FLAG for no file that all three readers opened. |
| Sizes | 271,360 to 16,818,176 bytes, with a median of 271,360 and a total of 128,454,656. 18 files are exactly 271,360 bytes long. |
| Empty files | 9 of the 32 files have no items at all. They are blank files from the Aspose test folder, and all three readers opened every one. |
| Passwords | 2 files store a password value. All three readers opened both without asking for one. |
| Items counted | In 28 files that all three opened, libpff and pst-extractor counted the same items in 25. In 3 OST files they did not. |
Two kinds, two outcomes
28 files show version 23, and 4 show version 36. The kinds predict how readers do. All three readers opened all 4 files with version 36. The 4 files that failed or split the readers all show version 23.
Of the 7 files named .ost, 2 show the PST letters SM. The name did not predict anything about the result. The 25 files named .pst and the 7 named .ost both included files that all three readers opened.
Where the three readers split
Three files split the readers. Sub.pst stopped libpff and pst-extractor, and readpst read it. Test_part0.pst and Test_part1.pst stopped libpff on a message, and the other two read them. We did not find out why, and we did not look inside the pages.
So refusing a file does not always mean the file is bad. libpff wanted every message to load, and two other readers read the same files. Test a file that one reader refuses with a second reader before you give up on it.
The file all three refused
AddingBulkMessages stopped all three readers. libpff says the header checksum does not match, and our script says the same. The file starts with !BDN and has the right size, so only the checksum shows that something is wrong.
Passing does not mean the same items
Of the 28 files that all three readers opened, libpff and pst-extractor counted the same items in 25. In the 3 largest OST files libpff counted 214, 183 and 162 items, and pst-extractor counted 70, 47 and 26.
In the largest of those files, one folder has 168 items, and pst-extractor returned 24 of them with its documented loop. The other 13 folders with items matched. We did not check which count is right. A pass shows that a reader walked the file. It does not show that two tools agree about it.
Passwords that did not stop anyone
Two files, passwordprotectedPST and passworded, store a password value in the message store. All three readers opened both with no password. Wikipedia notes Microsoft has acknowledged that the password adds little security. We did not test Outlook, so we cannot say what it asks.
Our script on the 32 files
Our script printed OK for 31 files and FLAG for 1. It printed FLAG for no file that all three readers opened. It printed OK for the 3 files that split the readers, so it cannot say which reader will refuse a file.
It reads the header and the size, and not the pages. That is why the damaged copies show it passing files that still stop a reader.
Read the study with care. It shows what three open readers do with 32 files from 4 projects. Outlook can be stricter or more lenient than any of them, and we had no copy of it. Mail archives from other sources can differ from ours.
What Happens When a PST File Is Damaged? 21 broken copies, and the three readers agreed on 16
We damaged one PST file in 21 ways. The three readers gave one answer on 16 copies and split on 5. Our script flagged or warned on 10. Our header repair script restored 4 of the copies, and it printed OK on 8 copies that still stopped a reader or lost mail.
The 21 copies come in three groups of 7. Group A changes the size or the start of the file, like the first bytes, the length and the bytes in front. Group B changes the header, like the version, the encoding byte, the size and the pointers. Group C changes the pages. Every copy changes one thing in example.
We asked three questions about every copy. Did a reader return the same four mails as the original, with the same subjects, body lengths and attachment counts? Did our script flag it? Did one script bring back a file that all three readers read?
Copies that split the readers
5 copies split the readers. B2 sets the encoding byte to 0, and only libpff read it. B4 flips one bit and keeps the old checksum, and libpff refused it while the other two read all four mails. B5 sets the size field to 0, and again only libpff refused.
C3 zeroes a page of 512 bytes. libpff returned one mail and then stopped, while the other two returned all four. C4 swaps two pages. libpff returned nothing, and the other two returned three of the four mails.
Copies every reader accepted
6 copies read the same in all three readers. A1 cuts the last byte, A2 cuts the file to half its length and A4 adds 1,024 zero bytes. C1 flips the bits of one byte, C2 zeroes 64 bytes and C5 zeroes the first allocation map page.
So a file that is shorter than its header says can still be read. Our script flagged A1 and A2 and warned on A4. The cut parts had pages that the four mails do not need. A3 cuts the file at 45,056 bytes, and all three readers refused it.
Copies every reader refused
10 copies were refused by all three readers. A3 cuts the file at 45,056 bytes. A5 adds 16 bytes in front, A6 zeroes the magic and A7 keeps 1,024 bytes. B1 claims the older ANSI version. B3 sets the encoding byte to 2. B6 and B7 zero a pointer in the header. C6 and C7 zero a root page.
The first bytes shape the result most. Once !BDN is gone or moved, no reader guesses where the header starts. C6 and C7 remove a tree, and the readers have no safe way to guess what the missing page said.
Readers agreed, and our script still passed
Our script printed OK for 11 copies. B2, B3, B6, B7, C3, C4, C6 and C7 still stopped a reader or lost mail. The script reads the header and the size. In these eight copies the header checks all pass, and the harm lies in a field or a page that it does not read.
That is why a pass proves little. The first four of those eight change a header field and fix the checksums, so the header still looks sound. The last four change a page.
Repairs that worked
Our script of 13 lines restored 4 copies. They are A5, A6, B4 and B5. After the repair, all three readers returned the same four mails as the original. For A5, A6 and B5 the repaired file matched the original byte for byte.
It cuts bytes in front of the magic and puts the magic back when the letters SM or SO follow. It sets the size field when it is 0 and signs both checksums again. B4 came back readable, but one flipped bit remains inside the header, so that file is not the original.
We found no free command that rebuilds the pages. Microsoft names the Inbox Repair tool for that job. We did not test it or any other repair program.
What no command restored
A3 and A7 lost most of the file. B1, B2, B3, B6 and B7 changed header fields that our script does not guess. C3 and C4 damaged pages, and C6 and C7 removed a root page. No rule shows what those bytes said.
Ask for the file again in all of those cases, or use a recovery tool that you trust and test it on a copy. Our script restored none of them, which leaves 11 of the 21 copies.
Read the grid with care. Every copy changes one thing in one small file. Damage in the wild changes many things at once. We opened no copy in Outlook, and our repairs rely on rules that fit the file we made.
What Does Our Expert Say About PST Files? A note from Neeraj Singh on comparing two readers
Check a PST file with two readers before you trust it. Our three readers gave different answers on 5 of 21 damaged copies. Our script printed OK for 8 copies that still stopped a reader or lost mail.
Expert insight
“A PST file can pass a quick test and still lose its mail. Our three readers gave one answer on 16 of 21 damaged copies, and our script printed OK on 8 copies that stopped a reader or lost mail. Compare two readers, and ask for a new file when the count looks wrong.”
Why one reader is not enough
A reader can return a count without an error. libpff returned one mail from C3 and then stopped, while the other two returned all four. A refusal warns you that something is wrong. A short count does not.
If your PST file opens in the program you trust and the folders look right, treat that as the best test. Use the readers on this page when it does not. libpff and readpst come from different projects, so they make a good pair.
Copy your PST file before you repair it. Work on the copy and keep the original untouched. Write down its SHA-256 hash first, so you can show later which file you started with.
How Do You Open a PST File? Outlook, three readers and what we tested
Microsoft Outlook is the program made for PST files, and we tested no copy of it. We tested three readers on Linux. readpst opened 31 of our 32 files, pst-extractor opened 30 and libpff opened 28. 28 files opened in all three, and the one file that failed in all three reports a header checksum mismatch.
The table lists the ways to open a PST file. Rows with version numbers are tools we tested on Linux. We tested no copy of Outlook, and we opened nothing on Windows or macOS.
| Program | What it does |
|---|---|
| Outlook | We tested no copy of Outlook. Microsoft Support says new Outlook opens a PST file only when classic Outlook is installed with the same bit width. The account needs a Microsoft 365 subscription. The ARM build does not support PST files. |
| libpff 20260926 | A C library with a Python binding named pypff. It opened 28 of our 32 files, and it prints folders, subjects and bodies. The libpff project is open source. |
| pst-extractor 1.12.0 | A TypeScript library for Node. It opened 30 files. The pst-extractor project says it is based on java-libpst. |
| readpst 0.6.76 | A command from libpst. It opened 31 files and writes MBOX or EML files. The Debian manual page lists its options. |
| java-libpst | A Java library. Its readme says it started from the libpff file notes. We cloned it for its test files and did not use it as a reader. The java-libpst project ships three of our files. |
| The file command | It read the bytes and named the version, Unicode and the encoding value for our example. |
| Other viewers | We tested no web converter, no viewer and no editor, so we make no claim about which versions read PST files. |
Open a PST file in Outlook
If you want to read the mail, open the file in Outlook. We tested none, so we name no version that fails. Microsoft's new Outlook notes list what new Outlook needs.
If Outlook shows nothing, the file can be damaged or can be another kind of file with the wrong ending. Look at the first bytes, or use our script to see what is wrong.
Open a PST file with Python or readpst
Eight lines of Python load the file and print every folder name with the subject of every message. The readpst command writes the mail to files without any code. These are the actual outputs for example.
import pypff
f = pypff.file()
f.open('example.pst')
def walk(fo):
for i in range(fo.number_of_sub_messages):
print(fo.name, repr(fo.get_sub_message(i).subject))
for j in range(fo.number_of_sub_folders):
walk(fo.get_sub_folder(j))
walk(f.get_root_folder())
tmp 'original email'
tmp 'FW: original email'
tmp 'FW: original email'
tmp 'FW: original email'
readpst -r -o out example.pst
Opening PST file and indexes...
Processing Folder "Deleted Items"
Processing Folder "Inbox"
"Outlook Data File" - 2 items done, 0 items skipped.
Processing Folder "tmp"
"Inbox" - 1 items done, 0 items skipped.
"tmp" - 4 items done, 0 items skipped.
The folder is named tmp, and it has the four mails. A reader gives you the mails, and Outlook decides how to show them.
Open an OST file the same way
All three readers opened all 7 of our files named .ost. Wikipedia calls OST the cache that Outlook uses for Cached Exchange Mode. The 5 with the letters SO opened like the rest. We did not test a live Exchange cache.
What to use for every task
Read the mail. Use Outlook. List the folders. Use pypff. Save the mail as files. Use readpst. Check the structure. Use our script. Test a file that one reader refuses. Try a second reader.
Install programs from their makers. Take libraries from their own project pages. A free web tool receives your mail, so try the steps on this page first.
How Do You Check a PST File? Six steps and a script of 24 lines
Check a PST file in six steps. Look at the first bytes, name the version, use a script and compare two readers. Our 24 line script printed OK for 31 of 32 files and flagged or warned on 10 of 21 damaged copies.
The first looks at a PST file need no Python. The file command names the version and the encoding, and xxd shows the magic. We used both on example.
xxd -l 32 example.pst
00000000: 2142 444e 8f38 3f3d 534d 1700 1300 0101 !BDN.8?=SM......
00000010: 0000 0000 0000 0000 0000 0000 0000 0000 ................
file -b example.pst | fold -s -w 76
Microsoft Outlook Personal Storage (>=2003, Unicode, version 23),
bidUnused=0000000000000000, dwUnique=0x54, 271360 bytes, bCryptMethod=1,
CRC32 0x99d7521e
A healthy file starts with !BDN, has a version at byte 10 and has a size field that equals its length. The Microsoft header page gives the same fields, so a file that breaks these points is damaged, or it is a test file made to break readers.
Check PST files with Python
The script reads the first 1,024 bytes. It checks the magic, the version and both checksums, and it compares the size field with the length of the file. It warns about extra bytes at the end and about the older ANSI kind.
It prints OK, WARN or FLAG, and it never changes a file. The checksum code is a table driven CRC with no final flip, and it matched the header in 31 of our 32 files. We tested no ANSI file, so the script skips its checks.
import struct,sys,os
T=[]
for i in range(256):
c=i
for _ in range(8): c=(c>>1)^0xEDB88320 if c&1 else c>>1
T.append(c)
def crc(b,c=0):
for x in b: c=T[(c^x)&255]^(c>>8)
return c
def peek(path):
b=open(path,'rb').read(1024); n=os.path.getsize(path)
if b[:4]!=b'!BDN': return 'FLAG','no !BDN at byte 0'
ver=struct.unpack('<H',b[10:12])[0]
if ver not in (14,15,23,36): return 'FLAG','unknown version %d'%ver
if ver<21: return 'WARN','older ANSI file: checks skipped'
if struct.unpack('<I',b[4:8])[0]!=crc(b[8:8+471]): return 'FLAG','header checksum does not match'
if struct.unpack('<I',b[524:528])[0]!=crc(b[8:524]): return 'FLAG','full header checksum does not match'
eof=struct.unpack('<Q',b[184:192])[0]
if eof==0: return 'FLAG','the file size in the header is zero'
if eof>n: return 'FLAG','file is %d bytes shorter than the header says'%(eof-n)
if eof<n: return 'WARN','%d extra bytes after the end the header gives'%(n-eof)
return 'OK','header and size agree'
if __name__=='__main__':
for p in sys.argv[1:]: print(os.path.basename(p),*peek(p))
Here is what it printed for our example and for four damaged copies.
python3 pst_peek.py example.pst
example.pst OK header and size agree
python3 pst_peek.py A5.pst B4.pst B5.pst C4.pst
A5.pst FLAG no !BDN at byte 0
B4.pst FLAG header checksum does not match
B5.pst FLAG the file size in the header is zero
C4.pst OK header and size agree
A5 has 16 bytes in front and gets a flag. B4 has a flipped bit, and B5 has a size of 0. C4 prints OK, and it still loses one mail in two readers and stops libpff before the first.
What the script found in our files
| Result | Cases |
|---|---|
| Printed OK (11 of 21 copies) | C1, C2 and C5 read fine in all three readers. B2, B3, B6, B7, C3, C4, C6 and C7 stopped a reader or lost mail, so OK is not a verdict. |
| Printed FLAG (8 of 21 copies) | The script names the first problem it finds, like no magic, a bad checksum or a file shorter than its header says. |
| Magic (A5, A6) | The script names a missing !BDN at byte 0. A5 adds 16 bytes in front and A6 zeroes the four bytes. All three readers refused both. |
| Size (A1, A2, A3, A7, B5) | The script names a file shorter than the header says, or a size field of 0. A1 and A2 still read fine, and A3, A7 and B5 stopped at least one reader. |
| Checksum (B4) | A flipped bit in the header with the old checksum. libpff refused it, and the other two read it. |
| Warned (A4, B1) | A4 adds 1,024 zero bytes and all three read it. B1 claims the older ANSI version, so the script skips its checks, and all three refused it. |
| Printed OK but stopped a reader (B2, B3, B6, B7) | The encoding byte or a pointer was changed and the checksums were signed again, so the header looks sound. |
| Printed OK but lost mail (C3, C4, C6, C7) | Zeroed or swapped pages. libpff returned one mail for C3 and none for C4, and all three refused C6 and C7. |
The script has limits. It cannot see inside a page, and it cannot know whether a pointer is right. It printed OK for 8 copies that still stop a reader or lose mail. The repair routes fix the kinds of damage we tested.
Check order for any PST file
- Copy your PST file, write its SHA-256 hash and work on the copy.
-
Look at the first bytes with
xxd -l 32. !BDN and a version is a PST file. See the three kinds. -
Name the version with
file -band the folders with pypff. - Use our script. The first word is OK, WARN or FLAG, and a flag names the problem.
- Open the file in two readers and compare the counts. The open steps show how.
- Look at the folders and the mail. We opened nothing in Outlook, so passes show a sound header for three readers only.
Is a PST File Safe to Open? Looking is safe, and the mail needs care
A PST file is stored data, so looking at one starts nothing. The risk lives in what you open afterward. One of our files has 71 messages with 70 attachments. We started none of them, and we scanned none of our files for malware.
Our readers loaded files and walked folders in empty folders, and the test files are public. We started no attachment, we scanned none for malware and we opened none in Outlook.
A PST file is a store of mail, and mail brings attachments. The Microsoft page on data files says people use a PST file to back up mail and to keep older items. A backup of old mail includes every attachment that arrived with it.
A password adds little. Wikipedia says Microsoft has acknowledged that the password in a PST file offers little security. Both of our password files opened in all three readers with no password.
What we found in our own files
We read the message classes in the 28 files that libpff opened. They include mail, appointments, contacts, distribution lists, tasks, meeting requests and delivery reports. In three of the OST files the appointments far outnumber the mail.
These are test files, and many were made to test those features. Do not read the counts as a share of everyday mail archives. They show that a PST file contains more than mail, and that a quick look at the first bytes cannot see it.
xxd, file and our script read bytes and start nothing inside the file.
Look at the file before you open it
Check the first bytes and the size. A proper PST file starts with !BDN and a version. If you see something else, check it with file -b and do not open it in Outlook until you know what it is.
Our biggest test file is 16,818,176 bytes. We did not test large files, so we give no size limit of our own. Microsoft Learn lists the limits for Outlook 2003 to 2016.
A PST file from someone else
Read the first bytes and use the script. Open the file in two readers and look at the folders. Work on a copy, and keep your software current.
Share a PST file with a helper
Send the output of our script and file -b, and not the mail. The first word of the script output shows a helper whether the header is sound. Keep the original, and share a copy only with someone you trust, because it contains private mail.
Not sure? Check it first. Copy the hash, look at the first bytes with our check steps and ask the sender for a fresh file if anything looks wrong. Open it last, on a copy.
Why Will Your PST File Not Open? Eight causes, and what to do about every one
Most PST files that will not open fail for one of eight reasons. Look at the first bytes, use the script and try a second reader. Our script flagged or warned on 10 of 21 damaged copies, and our repair script restored 4.
We damaged one PST file in 21 ways and tested a repair script on the copies. The table groups what we saw into eight causes.
Every row says what happens to your PST file and what to try next. Fixes work on copies, and none changes the original. We opened no repaired file in Outlook, so a repaired file shows only that three Linux readers can read it.
| Cause | Result and fix |
|---|---|
| A moved or zeroed magic (2) | A5 adds 16 bytes in front and A6 zeroes the first four bytes. All three readers refused both. Fix: Our script cuts the extra bytes or puts !BDN back. Both came back identical to the original. |
| A checksum that does not match (1) | B4 flips one bit and keeps the old checksum. libpff refused it, and the other two read it. Fix: Our script signs both checksums again, and B4 came back readable by all three. |
| A size field of 0 (1) | B5 sets the size to 0 and signs the checksums again. libpff refused it. Fix: Our script writes the length of the file into the field, and B5 came back identical to the original. |
| A file that is cut short (4) | A1 loses the last byte and A2 keeps half, and all three readers read both. A3 keeps 45,056 bytes and A7 keeps 1,024, and all three refused them. Fix: None for A3 and A7. The missing bytes are gone, so ask for the file again. |
| A wrong version or encoding byte (3) | B1 claims the older ANSI version and B3 sets the encoding byte to 2, and all three readers refused both. B2 sets it to 0, and only libpff read the file. Fix: None. Our script does not guess the right value. |
| A zeroed pointer or root page (4) | B6 and B7 zero a pointer in the header, and C6 and C7 zero a root page. All three readers refused all four. Fix: None. The pointer and the page are gone, so ask for the file again. |
| Damaged pages (2) | C3 zeroes a page and C4 swaps two. libpff stopped on both, and the other two returned all four mails for C3 and three for C4. Fix: None. Try a second reader and compare the counts. |
| Harmless changes (4) | A4 adds 1,024 zero bytes, C1 flips the bits of one byte, C2 zeroes 64 bytes and C5 zeroes the first allocation map page. All three readers returned the original four mails. Fix: None needed. |
When the file is not damaged
Four things look like a damaged PST file and are not. A file can be too big for the program. A password can stand in the way. A program can need extra parts. A file can differ from its ending.
Repairs we tested
A script of 13 lines covers the fixes that need our own code. It takes the damaged PST file and a name for the new file. It cuts junk in front of the magic, puts the magic back, sets a size of 0 to the length of the file and signs both checksums again.
import struct,sys
from pst_peek import crc
def fix(b):
i=b.find(b'!BDN',0,1024)
if i>0: b=b[i:]
elif i<0 and b[8:10] in (b'SM',b'SO'): b=b'!BDN'+b[4:]
if b[:4]!=b'!BDN' or struct.unpack('<H',b[10:12])[0]<21: return b
b=bytearray(b)
if struct.unpack('<Q',b[184:192])[0]==0: b[184:192]=struct.pack('<Q',len(b))
b[4:8]=struct.pack('<I',crc(bytes(b[8:8+471])))
b[524:528]=struct.pack('<I',crc(bytes(b[8:524])))
return bytes(b)
if __name__=='__main__': open(sys.argv[2],'wb').write(fix(open(sys.argv[1],'rb').read()))
# 1 magic moved (A5), magic zeroed (A6), checksum (B4), size field (B5)
python3 pst_fix.py A5.pst A5_fixed.pst
python3 pst_fix.py A6.pst A6_fixed.pst
python3 pst_fix.py B4.pst B4_fixed.pst
python3 pst_fix.py B5.pst B5_fixed.pst
# compare the short hashes with the original
for f in example.pst A5_fixed.pst A6_fixed.pst B4_fixed.pst B5_fixed.pst; do echo "$f $(sha256sum $f | cut -c1-12)"; done
example.pst 24c5e6bbb8bf
A5_fixed.pst 24c5e6bbb8bf
A6_fixed.pst 24c5e6bbb8bf
B4_fixed.pst 00c70be2dac7
B5_fixed.pst 24c5e6bbb8bf
The last lines print a short hash of every file. The hash matches for the original and the A5, A6 and B5 files, so those three came back byte for byte. B4 differs, because one flipped bit remains and the script signed the checksums to match it.
We also used the script on the one actual file that all three readers refused. It signed the checksums again, and our script then printed OK. All three readers still refused the file. The header of that file differs from a blank sibling in one byte, so a stale header is a good guess, but we did not prove it.
The script needs no other tool, and it rewrites only the header. We tested it on one small Unicode file. We did not test it on files with version 36 or on older ANSI files, so do not trust it there.
The Microsoft repair tool
Microsoft Support names the Inbox Repair tool, also called SCANPST.EXE, for PST files that will not open. It makes a .bak copy, and permanently deleted items and damage beyond repair stay lost. You can need several passes. For Exchange accounts Microsoft suggests deleting the OST file, because Outlook builds a new one.
We did not test it, and we make no claim about what it restores. If you use it, start it on a copy and keep the original untouched.
Fix PST files that will not open, step by step
We tested the steps on Linux with libpff 20260926, pst-extractor 1.12.0 and readpst 0.6.76. We opened no file in Outlook, and the steps keep the original untouched at every point.
- Copy your PST file, write its SHA-256 hash and work on the copy.
-
Name the start with
xxd -l 32and the kinds of PST file. A PST file starts with !BDN and has a version at byte 10. - Use the check script on this page. A flag or warning names the problem.
- Try a second reader. readpst and pst-extractor opened the most files, so use both.
- Match the answer to a cause in the table above and try its fix on the copy.
- If one fix fails, do not stack another on top. Go back to the copy and try the next cause.
- Open the result in two readers, then look at the folders and the mail.
What to send a helper
Short messages get faster answers. Include the details below and add the script output. Its first word gives OK, WARN or FLAG.
Subject: My PST file will not open
File: name, size in bytes and SHA-256 hash
Start: the output of xxd -l 32
Check: the output of pst_peek.py and file -b
Program: name, version and the exact words of the error
Source: where the file came from, and how it was sent
What no step can fix
Do not try online repair sites. Sites that offer to fix any mail file receive your upload, and a PST file contains private mail. Try the steps above on a copy first.
How Do You Convert a PST File to MBOX or EML? Tested routes, and what changed
readpst turned a 271,360 byte PST file with four mails into one MBOX file or four EML files. A bigger file of 13,984,768 bytes with 71 messages came out as 5 MBOX files, or 71 EML files. We tested no PDF, MSG or PST writing route.
People convert a PST file to use the mail somewhere else. The commands below do it from a terminal, and every number below is actual. We tested no web converter and no desktop converter.
Convert PST to MBOX
readpst -r -o out example.pst wrote one file named mbox into a folder tree that copies the folders of the PST file. In our tries the file came out at 34,155 to 34,169 bytes. The size changes by a few bytes from try to try, and we did not find out why.
The 13,984,768 byte file with 71 messages came out as 5 MBOX files of 16,186,364 to 16,186,408 bytes in total in our tries. The MBOX files are larger than the PST file. We did not break down the difference. The MBOX page explains the format.
readpst -r -o out example.pst
out/Outlook Data File/Inbox/tmp/mbox about 34 KB, 4 mails
readpst -r -o big enron.pst
big/ (5 mbox files) about 16.2 MB in total
Convert PST to EML
readpst -r -e -o out example.pst wrote 4 files named 1.eml to 4.eml, 33,923 to 33,965 bytes in total in our tries. The big file gave 71 EML files. The -e option names every file after its type, per the manual page. The EML page explains one message file.
One 2.3 MB test file with 7 mails came out as 7 EML files. One of them measured 2,155 bytes in one try and 8,825 bytes in two others. We did not find out why, so compare the files after you convert.
readpst -r -e -o out example.pst
out/Outlook Data File/Inbox/tmp/1.eml ... 4.eml
readpst -r -e -o big enron.pst 71 .eml files
Other routes we did not test
We did not test a PDF route, an MSG route or a way to write a new PST file. The MSG page covers the single message file that Outlook saves. We tested no desktop converter, so we make no claim about one.
The -D option adds deleted items per the manual page. We did not test it. A conversion can lose properties that a mail file has no place for, so keep the PST file after you convert.
file -b print the facts and write nothing.
Keep the original file. A converted copy can lose properties or items. Keep the PST file for later work.
How Does a PST File Differ From OST, EML and MBOX Files? One store, three neighbors, measured
A PST file stores folders of mail, an OST file caches mail and an EML file is one message. Our 4 mails were 271,360 bytes as a PST file and 33,923 to 33,965 bytes as four EML files. 7 of our files end in .ost, and 5 show the letters SO.
The table lists the neighbors of a PST file and what we measured. Sizes depend on the tool and the contents, so they show one case and not a rule. Our example PST file is mostly empty pages.
| Type | What separates it |
|---|---|
| PST | A store of folders with mail, contacts, calendar items and tasks. Our example was 271,360 bytes for four mails. |
| OST | The cache that Outlook uses for Cached Exchange Mode, per Wikipedia. 5 of our 7 files named .ost show the letters SO, and 2 show SM like a PST file. |
| EML | One message as text. Our four mails were four EML files of 33,923 to 33,965 bytes in total. Read the EML page below for the format. |
| MBOX | Many messages as text in one file. Our four mails were one MBOX file near 34 KB. Read the MBOX page below for the format. |
PST or OST
Both use one layout, and the header letters separate them. The OST files in our set open in the same readers. All 4 files with version 36 are OST files, so the newer page size shows up there first in our sample.
PST or EML
An EML file is one message and nothing else. A PST file has the folders around the messages, plus contacts and appointments. Converting to EML loses the folder file, so keep the PST file.
PST or MBOX
An MBOX file stores many messages as text in one file. readpst writes one MBOX file for every folder with mail. Our big file gave 5 MBOX files and about 16.2 MB, which is more than the PST file.
Which one do you have
What Is the PST File Format Made Of? The facts we could check, and where they came from
A PST file stores a header, pages and two trees. Facts below come from our own checks of 32 files and 21 damaged copies. Sources are Microsoft Learn, Microsoft Support, Wikipedia and the three test tools.
| Part | What we could check |
|---|---|
| Maker | Microsoft. Outlook 2003 brought the Unicode form with 64 bit pointers, and Outlook 2002 and earlier wrote the ANSI form, per Wikipedia. |
| Name | Personal Storage Table, with the ending .pst. The cache file ends in .ost. We did not look up a media type, so we give none. |
| First bytes | !BDN, a checksum and the letters SM. 27 of our 32 files say SM and 5 say SO. 28 say version 23 and 4 say 36. |
| Layout | A header, then pages. The Unicode header is 564 bytes with a magic value, a partial checksum, the version, a root, an encoding byte and a full checksum, per MS-PST. |
| Checksums | The partial checksum covers 471 bytes from byte 8, and the full checksum covers 516 bytes from byte 8 in the Unicode form, per MS-PST. Both matched in 31 of our 32 files. |
| Trees | A node tree and a block tree map folders, messages and data. In our example their root pages start at byte 49,152 and byte 38,912. |
| Encoding | Byte 513 shows 0 for none, 1 for the permutation form and 2 for the cyclic form, per MS-PST. Our 28 files with version 23 show 1, and the 4 others show 0. |
| Limits | Unicode files stop at 50 GB by default in Outlook 2010 to 2016 and at 20 GB in 2007 and 2003. The ANSI limit is 2,075,149,312 bytes, per Microsoft Learn. |
| Spec | MS-PST is the open specification. Its list names revision 11.2 on 18 February 2025, and Wikipedia says it falls under the Open Specification Promise. |
| Our tests | 32 files, 21 damaged copies, 3 readers, 1 header repair route and a script of 24 lines. libpff 20260926, pst-extractor 1.12.0 and readpst 0.6.76 on Linux. |
About the values we list
Facts about the layout come from our own reading of one example file and 32 test files, and from the pages we name. MS-PST from Microsoft is the specification, and the header table lists the fields.
The header page does not list version 36, and it gives only SM for the letters. Our sample has 4 and 5 files that differ. We did not read the rest of MS-PST, so we make no claim about rules for pages or trees.
What we left out
We opened no file in Outlook. We used no web converter and scanned no file for malware. We tested no ANSI file. Our readers and scripts worked on Linux, and Windows and macOS programs can accept or refuse files that they treat differently.
All 32 files come from 4 public projects, and many are made to test readers. Our damaged copies come from one small file and change one thing at a time. We did not test the Inbox Repair tool, and we did not read the Microsoft rules for passwords.
Sources checked
For the format, see MS-PST, the header page, the Wikipedia article on the Personal Storage Table and the Microsoft size limit page.
For the tools, see libpff, pst-extractor on GitHub, the readpst manual and Microsoft Support on PST files. The test files come from four public projects. Every count on this page came from files and scripts in our research folder.
Frequently Asked Questions About PST Files
What is a PST file?
A PST file is an Outlook data file that stores mail, contacts, calendar items and tasks. The name means Personal Storage Table. Microsoft made the format, and Outlook 2003 brought the Unicode form, per Wikipedia.
How do I open a PST file?
Open it in Outlook. We also tested libpff, pst-extractor and readpst. readpst opened 31 of our 32 files, pst-extractor opened 30 and libpff opened 28. New Outlook also needs classic Outlook, per Microsoft Support.
Why will my PST file not open?
The file can be damaged, cut short or the wrong kind. One reader alone refused 3 of our 32 files that another read. Try a second reader before you give up. Microsoft names the Inbox Repair tool for damaged files.
What is the difference between a PST and an OST?
A PST file is a store of mail, and an OST file is the cache Outlook uses for Cached Exchange Mode, per Wikipedia. Both use one layout. 5 of our 7 OST files show the letters SO in the header, and 2 show SM.
Is a PST file safe to open?
Looking at the bytes starts nothing. The risk lives in the attachments and links in the mail. One of our files has 71 messages with 70 attachments. A password adds little security. Keep Outlook current.
How do I convert a PST file to MBOX?
Use readpst. readpst -r -o out example.pst wrote one MBOX file with four mails near 34 KB. A 13,984,768 byte file with 71 messages gave 5 MBOX files and about 16.2 MB.
How do I convert a PST file to EML?
Use readpst with -e. readpst -r -e -o out example.pst wrote 4 EML files, and the big test file gave 71. Compare the files after you convert, because one EML file changed size between our tries.
How can I check if a PST file is damaged?
Look at the first bytes, use our script and compare two readers. The script flagged or warned on 10 of 21 damaged copies, and it printed OK for 8 that still stopped a reader or lost mail. Look at the folders too.
Can a damaged PST file be repaired?
Some header damage can be repaired. Our script restored 4 copies by fixing the magic, the size field and the checksums. Zeroed pages and cut files did not come back. Keep the original and work on a copy.
Do all readers agree on a damaged PST file?
No. Our three readers gave one answer on 16 of 21 damaged copies and split on 5. libpff stopped on a copy that the other two read in full. Compare two readers.
How big can a PST file be?
Unicode files stop at 50 GB by default in Outlook 2010 to 2016 and at 20 GB in 2007 and 2003, per Microsoft Learn. The older ANSI form stops near 2 GB. Our biggest test file is 16,818,176 bytes.
Does a PST file need a password to open?
Not in our tests. Both password files opened in all three readers with no password. Wikipedia says Microsoft has acknowledged that the password adds little security. We did not test what Outlook asks.
Still Stuck With a PST File? Where to go next, depending on what went wrong
Look at the first bytes and use the check script. The cause table lists what to try in order.
The kinds table names the kind, and the neighbors name the formats that look alike.
Is it an EML file? The guide to EML files covers one message saved as text.
Is it an MBOX file? The guide to MBOX files covers many messages in one text file.
Is it an MSG file? The guide to MSG files covers the single message that Outlook saves.
Did it come with a winmail.dat file? The guide to DAT files covers the attachment that Outlook sends.
Is it a file type you do not know? Browse the file extension resource library, or send it on the submit a file type page.
Do you need the format facts? Read the format part for the layout, the limits and the sources of PST files.