libplist reads and writes Apple property lists from C, on Linux, macOS and Windows
A library to handle Apple Property List format in binary or XML
At a glance
- What is it?
- The libimobiledevice/libplist library is a small portable C library for the binary, XML, JSON and OpenStep property list formats, with a plistutil command line tool and Cython bindings. It builds with autotools and ships as LGPL-2.1.
- Who is it for?
- Adopt libplist if you need reliable property list parsing in C, if you want one tool that converts between the binary, XML, JSON and OpenStep formats, or if your tooling already links libimobiledevice and its sibling projects.
- Can I use it commercially?
- Yes, with conditions. LGPL-2.1 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 23 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One library for four property list formats
libplist is described as a small portable C library to handle Apple Property List files in binary, XML, JSON, or OpenStep format. That is the entire scope, and it is worth having precisely because the format is a persistent nuisance in Apple ecosystem tooling. A plist file you receive from a device, a backup, an Xcode artefact or a third party application may be in any of several encodings, and code that assumes one of them breaks on the others. The project provides an interface to read and write plist files in all four formats, and the listed features call out the format support explicitly. The audience is developers of the kind of tooling that already has to speak this dialect: the library is used in libimobiledevice and its corresponding projects, so if your tool reads data from an iOS device, this is likely already a transitive dependency of your stack rather than something you would choose from scratch.
plistutil handles the conversion case
Not every use of a plist library needs C. The project also ships a command line utility named plistutil, described as really easy to use, and the documentation gives the whole invocation:
plistutil -i foobar.plist -o output.plistThe utility takes an input file and an output file, which is the shape you want for format conversion and for inspecting an unfamiliar plist without writing any code. If you are reaching for libplist because a plist has to be translated into JSON before another tool can read it, this binary covers the case and the library is only needed when the plist has to be handled inside a running process. The repository layout backs up the claim that this is a full library and not just a converter, with src/, include/, the Cython directory cython/, the fuzzing directory fuzz/, the test directory test/, and tools/ at the root.
Linux builds need the autotools prerequisites
The build uses autotools so the same steps work across platforms, and only the prerequisites differ. On a Debian or Ubuntu system the documentation asks for the build tools and the autotools suite:
sudo apt-get install \
build-essential \
checkinstall \
git \
autoconf \
automake \
libtool-binThe optional pieces are separate, because the documentation and the Python bindings are not needed for the library itself. If you want to build the documentation or the Python bindings, the extra packages are doxygen and cython3. That separation is a hint about the shape of the project: the core is a C library with an autotools build, and the documentation and the language bindings are add-ons layered on top.
macOS needs either MacPorts or Homebrew, and careful environment variables
On macOS the requirement is the Xcode command line tools, plus automake, autoconf and libtool installed through one of the two usual package managers. With MacPorts:
sudo port install libtool autoconf automakeOr with Homebrew:
brew install libtool autoconf automakeThe Python bindings are the fiddly part on this platform, because the build has to be told where the interpreter and its libraries live. The documentation lists the environment variables the automated GitHub Actions build sets:
PYTHON3_BIN=`xcrun -f python3`
export PYTHON=$PYTHON3_BIN
PYTHON_VER=`$PYTHON3_BIN -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('VERSION'))"`
PYTHON_EXEC_PREFIX=`$PYTHON3_BIN -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('exec_prefix'))"`
PYTHON_LIBS_PATH=$PYTHON_EXEC_PREFIX/lib
PYTHON_FRAMEWORK_PATH=$PYTHON_EXEC_PREFIX/Python3
export PYTHON_LIBS="-L$PYTHON_LIBS_PATH -lpython$PYTHON_VER"
export PYTHON_EXTRA_LDFLAGS="-Wl,-stack_size,1000000 -framework CoreFoundation $PYTHON_FRAMEWORK_PATH"Those variables query distutils.sysconfig to discover the interpreter version and prefix. Check them against your own Python before copying them, because the module they rely on has been deprecated and removed from recent Python versions, and this is exactly the kind of instruction that ages quietly.
Windows goes through MSYS2 and pacman
The documented route for Windows is MSYS2, which the project calls the official way of compiling on that platform, using the MSYS2 MinGW 64-bit shell. Inside that shell the toolchain comes from pacman:
pacman -S base-devel \
git \
mingw-w64-x86_64-gcc \
make \
libtool \
autoconf \
automake-wrapperThe documentation also notes that another shell and another compiler can be used and that the command can be adapted accordingly, which is the honest position for a Unix toolchain. Python bindings on Windows need cython installed through the same package manager, plus a working Python environment. Note what is not here: no Visual Studio project files, no prebuilt binaries. If your build system for Windows expects an MSBuild artefact, this repository does not provide one, and the MSYS2 route has to be wrapped by whatever you use.
Git checkout and release tarball configure differently
You can build from a git checkout or from a .tar.bz2 release tarball, and the difference is one script. From git you clone and change into the directory:
git clone https://github.com/libimobiledevice/libplist.git
cd libplistand then run the autogen script, which generates and calls configure:
./autogen.shFrom a tarball named libplist-x.y.z.tar.bz2 you extract and change into it:
tar xjf libplist-x.y.z.tar.bz2
cd libplist-x.y.zand run configure directly:
./configureBoth accept options, and the two worth knowing are --enable-debug, which allows printing debug messages in the final product, and --without-cython, which skips building the Python bindings:
./autogen.sh --prefix=/usr/local --enable-debug --without-cythonWhen the configuration succeeds, the tail of the output tells you what was decided:
[...]
config.status: creating config.h
config.status: executing depfiles commands
config.status: executing libtool commands
Configuration for libplist 2.3.1:
-------------------------------------------
Install prefix ..........: /usr/local
Debug code ..............: yes
Python bindings .........: yes
Now type 'make' to build libplist 2.3.1,
and then 'make install' for installation.That sample output is from version 2.3.1 while the current release is 2.8.0, a small reminder that the documentation in this repository is written against an older build than the code it ships.
make, install, and the library cache step on Linux
Building and installing is deliberately dull. The build is:
makeand the install is either of these, depending on whether your user can write to the destination directory:
make installor:
sudo make installOn Linux there is one extra step the documentation insists on, running sudo ldconfig after installation so the installed libraries are made available to the loader. Skipping it produces the classic symptom of a library that is installed but not found at runtime. Everything else about the workflow is the standard autotools sequence, which is a genuine advantage for anyone who has built C libraries before and a reason the project can support three platforms without maintaining three build systems.
Testing, fuzzing, releases and the LGPL terms
The project's stated quality approach is testing rather than assertion: it uses fuzzing through OSS-Fuzz and data compliance tests, and describes itself as a lean library with performance and resources in mind. Python bindings are provided through Cython, and the repository holds a fuzz/ directory alongside the test/ directory, so the testing claim has files behind it. Release history shows the project moving steadily, with 2.6.0 on 2024-05-13, 2.7.0 on 2025-05-14 and 2.8.0 on 2026-09-29, and the last push was on 2026-09-29. The licence is LGPL-2.1, with COPYING and COPYING.LESSER at the repository root. LGPL is a weak copyleft licence, which in practice means linking is permitted while modifications to the library itself carry source disclosure obligations, and the exact shape of your obligations depends on how you distribute the result. That describes the licence rather than giving legal advice, and it is the one thing to check before you vendor this code into a closed product.
Editorial conclusion
Adopt libplist if you need reliable property list parsing in C, if you want one tool that converts between the binary, XML, JSON and OpenStep formats, or if your tooling already links libimobiledevice and its sibling projects. Do not adopt it if you need a maintained package from your distribution rather than a source build, since the documented path is autotools from a checkout or a release tarball, and expect the LGPL-2.1 terms to shape how you ship it, with COPYING and COPYING.LESSER at the repository root. Before you start, confirm your toolchain has autoconf, automake and libtool, decide whether you need the Python bindings because they pull in Cython, and check that plistutil handles the format mix in your data before you rewrite your importer around it.
Frequently asked questions
What formats does libplist support?
The library reads and writes Apple property list files in binary, XML, JSON and OpenStep format. It is a small portable C library, and the project ships a command line utility named plistutil alongside it.
How do I build libplist from a git checkout on Linux?
Install the autotools prerequisites, clone the repository, change into the libplist directory and run ./autogen.sh, then run make and make install. On Linux you also need to run sudo ldconfig after installation so the installed libraries are found.
Can I skip the Python bindings when building libplist?
Yes. Both ./configure and ./autogen.sh accept --without-cython to skip building the Python bindings, and the configuration summary at the end of the run reports whether Python bindings are enabled.
How do I convert a plist file with plistutil?
The documented invocation is plistutil -i foobar.plist -o output.plist, which takes an input file and writes an output file. The project describes the utility as really easy to use, and it is the option that avoids writing C for a one off conversion.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/libimobiledevice-libplist)Was this useful?