What Is a PLIST? Apple's Property List Format
The Short Answer: A Structured Container for App Data
A PLIST file—short for Property List—is Apple's go-to format for storing configuration settings, preferences, and serialized data across its entire ecosystem: macOS, iOS, iPadOS, watchOS, and tvOS. Its roots stretch all the way back to NeXTSTEP in the late 1980s, and it remains the backbone of how your apps remember your choices, how system services load their configurations, and how Xcode projects describe what to build. You have hundreds of PLIST files on your Mac right now, whether you realize it or not. Pop open Terminal and run `ls ~/Library/Preferences/`. You'll see a long list of files like `com.apple.finder.plist`, `com.apple.dock.plist`, and many others—one for nearly every application you've ever used. These simple files are what tell the Finder how wide your sidebar should be, tell the Dock where your icons live, and remind Safari which tabs were open when you last quit. The format supports a small, fixed set of data types: strings, integers, floating-point numbers, booleans, dates, binary data (Data), arrays, and dictionaries. That's the entire list. There are no custom types, no inheritance, and no schemas. This isn't an oversight; it's a deliberate design choice. Apple needed a format that the OS could read and write with minimal overhead, and one that was simple enough to survive a manual edit without immediately corrupting an app's state.
XML vs. Binary vs. JSON: Three Flavors of the Same Format
While there is one PLIST format, it comes in three distinct encodings. Mixing them up is a common source of confusion. First is the **XML PLIST**, the human-readable version. Crack one open in a text editor and you'll see a DOCTYPE declaration pointing to `http://www.apple.com/DTDs/PropertyList-1.0.dtd`, followed by a sea of nested tags: `<dict>`, `<key>`, `<string>`, `<integer>`, `<true/>`. Xcode uses this for its project files (`project.pbxproj` is a variant), and it's what you want when exporting settings for backup or inspection. The obvious downside is verbosity. A simple dictionary with 20 keys can easily sprawl across 150 lines. For performance, macOS almost always uses **Binary PLIST** (bplist) when writing files to disk. When an app saves its preferences, it's typically writing a file that starts with the magic bytes `bplist00`. This format is significantly more compact and much faster to parse than its XML cousin. That 150-line XML file might shrink to a mere 400 bytes in binary form. The trade-off is that you can't read binary PLISTs in a standard text editor; they just look like garbled characters. Finally, there's **JSON PLIST**, a newer option supported since macOS 10.7. It uses standard JSON syntax, but it's still constrained to the core PLIST data types. This one is a bit of an oddball. JSON doesn't natively distinguish integers from floats or have a dedicated Date type, which introduces some subtle limitations. You'll rarely see Apple's own tools produce JSON PLISTs; they mostly appear when third-party build tools or CI pipelines are generating configuration files. Thankfully, you can easily convert between all three with Apple's built-in `plutil` command-line tool. A command like `plutil -convert xml1 com.apple.dock.plist -o dock_readable.plist` gives you a human-readable copy of your Dock preferences without modifying the original binary file.
Where PLIST Files Live and What They Control
Knowing where to find PLIST files is half the battle when you're troubleshooting a misbehaving app or migrating settings to a new machine. They live in a few predictable places. Your personal application settings are stored in `~/Library/Preferences/`. This is where your custom Dock layout, your Terminal color scheme, and your Xcode key bindings reside, all tied to your specific user account. The filenames follow a reverse-DNS naming scheme, like `com.apple.Terminal.plist` or `com.googlecode.iterm2.plist`. In contrast, settings that apply to every user on a Mac are found in `/Library/Preferences/`. These control system-wide behaviors like network configuration and time zone, and they typically require administrator privileges to modify. PLISTs do more than just store preferences; they also drive the macOS automation system. The files in `/Library/LaunchAgents/`, `/Library/LaunchDaemons/`, and the user-specific `~/Library/` versions are what define background services and scheduled tasks. A LaunchDaemon PLIST tells the `launchctl` service what executable to run, which arguments to pass, whether to restart it on a crash, and its schedule. Perhaps the most critical of all is the `Info.plist` file tucked inside every `.app` package. Right-click any app in Finder, choose Show Package Contents, and navigate to `Contents/Info.plist` to see it. This file is the app's official identity card, declaring its bundle identifier, minimum OS version, required hardware capabilities, URL schemes, and permissions it needs (like camera or microphone access). On iOS, the `Info.plist` is what the App Store and the OS itself use to decide if your app can even run on a given device. A crucial word of warning: if you plan to edit a file in `~/Library/Preferences/`, always quit the corresponding app first. Reading a file while the app is running is fine, but if you write changes, the app will likely overwrite them the next time it saves its state. Quit the app, make your edits, then relaunch.
Reading and Editing PLIST Files: Your Practical Options
Apple provides a full toolkit for reading and modifying PLIST files, ranging from polished graphical interfaces to powerful command-line utilities. For most developers, **Xcode's built-in PLIST editor** is the best place to start. It opens any PLIST file in a structured tree view with type-aware editing: you get checkboxes for booleans, date pickers for Date values, and neatly expandable arrays and dictionaries. You can add, delete, and reorder keys without ever touching raw XML. This is the standard, sanctioned workflow for editing `Info.plist` and entitlement files. For scripting and automation, the **`plutil` command-line tool** is indispensable. It ships with macOS and is a powerhouse for validation, conversion, and key-level editing. `plutil -lint myfile.plist` quickly checks for syntax errors, while a command like `plutil -replace NSHighResolutionCapable -bool YES MyApp.app/Contents/Info.plist` can set a single key without opening an editor. It's a must-have for shell scripts and CI/CD pipelines. When you want to change user preferences, the **`defaults` command** is the correct tool for the job. You can read a current setting with `defaults read com.apple.finder ShowPathbar` or change it with `defaults write com.apple.finder ShowPathbar -bool TRUE`. This is precisely why so many macOS "power user" customizations are shared as simple `defaults write` one-liner commands. Sometimes you need more power. **Third-party editors** like PlistEdit Pro (around $12 on the Mac App Store as of 2025) add features that Xcode lacks, such as side-by-side comparison, direct binary PLIST editing without conversion, and batch operations. If you find yourself wrestling with PLISTs daily, a dedicated tool is a smart investment. And what about a simple **text editor**? It works perfectly for XML PLISTs, but it will corrupt binary ones. If you open a binary file in VS Code or BBEdit, you must first convert it to XML with `plutil -convert xml1`. After editing, convert it back with `plutil -convert binary1` before the system can use it.
Converting PLIST Files: What CocoConvert Can and Can't Do
CocoConvert is built to handle the most common PLIST conversion scenarios people face on the web: converting XML PLISTs to JSON, turning JSON into XML PLIST, and decoding binary PLIST files into readable XML without needing developer tools. For XML-to-JSON conversion, CocoConvert maps the PLIST data types to their JSON equivalents. Strings, integers, arrays, and dictionaries convert cleanly. Booleans become JSON `true` and `false`. Dates are serialized into standard ISO 8601 strings (e.g., `2024-11-03T14:22:00Z`). Any binary data from `<data>` elements is base64-encoded in the output, which preserves the content perfectly but means those specific fields in the JSON won't be human-readable. The binary-to-XML feature is particularly useful. If you've ever exported a preferences backup from an iPhone using a third-party tool, CocoConvert can parse the resulting `bplist` file and produce a readable XML PLIST, letting you inspect its contents without installing Xcode on your machine. We also need to be clear about what CocoConvert can't do: it cannot convert PLIST files back into the binary format. Generating a binary PLIST requires building precise byte-level offset tables, a task that is simple for Apple's native libraries but very difficult to implement correctly in a web service. If you need to write a modified binary PLIST back to a device—to restore edited iPhone preferences, for example—you must use `plutil` on a Mac or a native editor like PlistEdit Pro. While macOS can often read an XML file where a binary one is expected, some apps are strict and will reject or ignore the XML version. CocoConvert also validates structure, not semantics. A PLIST with a malformed bundle identifier or an invalid OS version will convert just fine, because from a file format perspective, it's valid. Those are application-level concerns that a format converter can't diagnose.
Common PLIST Problems and How to Diagnose Them
PLIST corruption is rare, but it's a uniquely frustrating macOS troubleshooting scenario. The symptoms—an app that won't launch, preferences that reset on every reboot, a system service that silently fails—rarely point directly to a specific file. The most frequent cause is **corruption from an improper write**. If macOS crashes or loses power while an app is saving its settings, the PLIST on disk can end up truncated or garbled. Your first diagnostic step should be `plutil -lint ~/Library/Preferences/com.example.app.plist`. A healthy file returns `OK`; a corrupted one gives a parse error, usually with a helpful line number or byte offset. **Permission problems** are a close second. A PLIST file in a user's `~/Library/Preferences/` directory that is somehow owned by `root` will cause an app to silently fall back to its default settings on every single launch. Check ownership with `ls -l ~/Library/Preferences/com.example.app.plist`—the owner must be your username, not `root`. You can fix it with `sudo chown $(whoami) ~/Library/Preferences/com.example.app.plist`. An even subtler issue is **cached preferences**. To be faster, macOS uses a background daemon, `cfprefsd`, to cache preference values. This means that even if you directly edit a PLIST file on disk, the running app may continue reading the old, cached version. If your `defaults write` changes aren't taking effect, this is almost certainly why. Force a cache flush with `killall cfprefsd` (it restarts automatically) or simply log out and back in. Xcode build failures often trace back to a malformed `Info.plist`. The build will fail with a vague error like "The data couldn't be read because it isn't in the correct format," which is just Xcode's way of saying the file failed to parse. Before you do anything else, check for merge conflict markers like `<<<<<<<` in the XML, or just run `plutil -lint` on the file. For any PLIST you didn't create yourself — one from a device backup, a GitHub repo, or a colleague — run `plutil -lint` on it first. It takes three seconds and saves a world of confusion.
PLIST in the Broader Apple Development Workflow
Beyond simply storing preferences, PLIST files are load-bearing infrastructure in Apple's development toolchain, often in ways that only become obvious when something breaks. An app's code signing hinges on an entitlements PLIST. This is the file that declares exactly which special capabilities an app is permitted to use: iCloud, push notifications, App Groups, Keychain sharing, and so on. This file is embedded directly into the app's code signature during the build. If the entitlements PLIST doesn't match the provisioning profile, the app simply won't install on a device. Apple's `codesign` tool reads and validates this file directly. Xcode's build system itself leans heavily on PLISTs. The `*.xcscheme` files found inside `.xcodeproj/xcshareddata/xcschemes/` are PLISTs that describe which targets to build, what arguments to pass on launch, and which environment variables to set. Because they are just structured XML, they are safe to commit to version control and are easy to diff between branches. Even App Store submission metadata is managed by a PLIST. The privacy manifest (`PrivacyInfo.xcprivacy`), introduced in Xcode 15 and required for most app submissions after May 2024, is a PLIST file. It declares which APIs your app uses that could potentially be used for fingerprinting, and why. Getting this file wrong doesn't cause a build error; it causes an App Store review rejection, which is significantly more annoying to debug. For anyone building cross-platform tools that interact with Apple's ecosystem—CI systems, MDM solutions, or backup utilities—a deep understanding of the PLIST format is unavoidable. The format spec is documented in Apple's `CFPropertyList` reference, but the binary format has also been thoroughly reverse-engineered. Excellent open-source parsers exist for Python, Ruby, Go, and Rust. The `plistlib` module in Python's standard library (since 3.4) is particularly reliable for production scripts that need to process device backups or Xcode project files.