PLIST File Documentation
Summary
A plist (Apple Property List) file stores settings and structured data for macOS and iOS as keyed dictionaries, arrays, strings, numbers, dates and booleans. It comes in two encodings under one extension: human-readable XML, or a compact binary form that starts with the bytes bplist00. Its MIME type is application/x-plist. Open an XML .plist in any text editor; convert a binary one with plutil -convert xml1 file.plist on a Mac. Most plists are app internals you should not hand-edit blindly.
Technical details
| Feature | Value |
|---|---|
| Full name | Apple Property List |
| File extension | .plist |
| MIME type | application/x-plist |
| Format type | Serialized settings: XML text or binary bplist |
| Developer | Apple (originally NeXT) |
| Introduced | NeXTSTEP (late 1980s); XML/binary forms with Mac OS X 10.0 (2001) |
| Encodings | XML, binary (bplist00), legacy NeXT/OpenStep ASCII |
| Binary magic | 62 70 6C 69 73 74 30 30 (“bplist00”) |
| XML header | <?xml + <!DOCTYPE plist + <plist version…> |
| Value types | dict, array, string, integer, real, true/false, date, data |
| Byte order | Big-endian (binary form) |
| Typical use | Info.plist in app bundles; prefs in ~/Library/Preferences |
| Convert tool | plutil (macOS), plistutil (Linux/Windows) |
| Editor | Xcode property-list editor; any text editor (XML) |
| Managed by | cfprefsd daemon; defaults command |
| Open standard | Partial (public DTD; binary format documented by Apple/libplist) |
| Related extensions | .xml, .mobileconfig, .strings, .entitlements, .json |
| Specification | developer.apple.com — About Property Lists |
What is a plist file?
A property list, or plist, is Apple’s standard way of serialising structured settings: dictionaries, arrays, strings, numbers, booleans, dates and raw data. The concept comes from NeXTSTEP in the late 1980s and became central to Mac OS X on its 2001 release and later to iOS. Every macOS and iOS app ships an Info.plist that declares its bundle identifier, version, required capabilities and permission usage strings; user preferences are stored as plists under ~/Library/Preferences, managed by the defaults system and the cfprefsd daemon.
The wrinkle that trips people up is that one extension covers two very different encodings. A plist can be a readable XML document, or a compact binary blob that begins with the bytes bplist00 and looks like garbage in a text editor. There is also a legacy NeXT/OpenStep ASCII form, now rare. The data is identical across encodings and round-trips losslessly between them; only the bytes on disk differ. The sections below cover the value model, the XML form, the binary form field by field, and why editing a live preferences plist by hand often does not stick.
The value model: eight types under a root container
Whatever the encoding, a plist represents the same small, fixed set of types. The document is a single root value, almost always a dictionary or an array, which nests the rest.
| plist type | XML tag | Holds |
|---|---|---|
| Dictionary | <dict> | ordered <key> / value pairs |
| Array | <array> | an ordered list of values |
| String | <string> | Unicode text |
| Integer / real | <integer> / <real> | numbers |
| Boolean | <true/> / <false/> | a flag |
| Date | <date> | ISO-8601 timestamp |
| Data | <data> | base64-encoded bytes |
A dictionary is where most configuration lives: each entry is a <key> naming a value that follows it. This is the same conceptual model as JSON, which is why plutil can convert many plists to JSON; the differences are that plist adds first-class date and data types JSON lacks, and that a plist dictionary’s keys are written as separate elements rather than as "key": value pairs.
The XML form: DOCTYPE, DTD and structure
An XML plist is a normal XML 1.0 document with a specific document type. It has no binary magic number; it is recognised by its opening declarations.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>com.example.app</string>
<key>CFBundleVersion</key>
<string>1.2.0</string>
<key>LSMinimumSystemVersion</key>
<string>12.0</string>
</dict>
</plist>
The <!DOCTYPE> line points at Apple’s public DTD, which formally defines the allowed elements. The single <plist> root wraps one value. Because it is plain UTF-8 text, this form opens in any editor on any OS, which is why so much troubleshooting advice can say “edit the plist” without naming a Mac-only tool. The trade-off is size and parse speed, which is what the binary form addresses.
The binary form: header, objects, offset table, trailer
A binary plist is built for apps to load quickly and store compactly. It has four regions in order: an 8-byte header, an object table, an offset table, and a 32-byte trailer at the very end.
bplist layout
header "bplist00" (8 bytes)
object table every value, each prefixed by a 1-byte marker
offset table file offset of each object (uint of fixed width)
trailer 32 bytes, at end of file:
6 unused
1 offset-table entry size (1-4 bytes)
1 object-reference size (1-4 bytes)
8 number of objects
8 index of the top (root) object
8 offset where the offset table starts
Each object in the object table starts with a single marker byte whose high nibble encodes the type (integer, string, dict, array and so on) and whose low nibble usually encodes the length, with an escape for larger sizes. Containers do not store their children inline; they store object references, which are indices into the offset table. The offset table then lists the absolute file offset of every object, so reference n resolves to the object at the nth offset. The trailer is read first (parsers seek to the last 32 bytes): it gives the byte-width of an offset-table entry, the byte-width of an object reference, the total object count, which object is the root, and where the offset table begins. From those five numbers a reader can walk the whole graph. This indirection is what lets a binary plist deduplicate repeated values and stay small, and it is why the format is faster for an app to load than re-parsing XML.
Converting between encodings with plutil
Because the two encodings carry the same data, macOS ships plutil to move between them and to validate syntax. This is the load-bearing command for anyone facing an unreadable plist.
plutil -convert xml1 file.plist # binary -> readable XML
plutil -convert binary1 file.plist # XML -> compact binary
plutil -convert json file.plist # -> JSON (data/date become base64/strings)
plutil -p file.plist # print a human-friendly tree
plutil -lint file.plist # validate syntax
On Linux and Windows the equivalent is plistutil from libplist (part of libimobiledevice, the toolkit that reads iPhone backups). Converting to JSON is lossy in one direction: a plist <data> becomes a base64 string and a <date> becomes a text string, because JSON has no native type for either, so a JSON → plist round trip does not restore those types automatically.
Why hand-editing a preferences plist may not stick
On modern macOS the preference plists under ~/Library/Preferences are not simple files an app reads on demand. They are cached in memory and written back by the cfprefsd daemon, which owns the in-memory copy while an app is running. Editing such a plist by hand in a text editor while the owning process is live often has no effect, because cfprefsd later flushes its cached version over your change. The supported route is the defaults command (for example defaults write com.example.app SomeKey -bool true), which goes through the same daemon so the change is seen and persisted. This caching is specific to the preferences domain; a plist you own, such as one inside your own app bundle or a config file, can be edited directly.
Frequently asked questions
Why is my .plist file full of unreadable characters?
It is a binary plist, not XML. The file starts with the bytes bplist00 and stores its values in a packed object table, so a text editor shows raw bytes. Convert it to readable XML first with plutil -convert xml1 file.plist on macOS, or plistutil on Linux and Windows, then open the result.
Can I open a plist on Windows?
An XML plist opens in any text editor such as VS Code or Notepad++, because it is plain UTF-8 text. A binary plist needs converting first, since Windows has no built-in plist support; use plistutil from libimobiledevice to turn bplist00 data into XML, then read it.
References
- Apple — About Property Lists (archive)
- Apple — plutil(1) manual page
- libplist — open-source plist library (plistutil)
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.