Picamera2: the libcamera era replacement for the original Picamera library
New libcamera based python library
At a glance
- What is it?
- Picamera2 is the Raspberry Pi's libcamera based Python camera interface, replacing the legacy stack wrapper and carrying a deliberate policy of not changing APIs without reason. It suits anyone moving a Raspberry Pi project off the old camera stack, and the compatibility rules are narrower than the name suggests.
- Who is it for?
- Picamera2 fits a project that has to run on a current Raspberry Pi OS image and wants the camera driven through libcamera rather than the retired legacy stack, because the library wraps the modern pipeline and keeps the API small enough to read. Skip it if you need the old Picamera API, since this is a replacement rather than a compatibility layer, and skip it if your image still has the legacy stack enabled, because the library is explicitly not supported there.
- Can I use it commercially?
- Yes. BSD-2-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A replacement, not a compatibility layer
Picamera2 is the libcamera based replacement for Picamera, which was a Python interface to the Raspberry Pi's legacy camera stack. Picamera2 also presents an easy to use Python API.
That first sentence sets the scope. This is not a shim that lets old Picamera code keep running, it is a new library written against the modern camera pipeline, and the two coexist on the same hardware only in the sense that the legacy stack can be re-enabled, which is exactly the configuration Picamera2 does not support.
The project describes itself as currently available as a beta release, with the consequences spelled out. There may still be some issues and bugs which the maintainers will work on fixing, and where users identify particularly useful features they may still consider implementing them. Mostly the work will be on bugs, stability, support, examples and documentation, as well as keeping up with ongoing libcamera development.
And then there is the sentence that tells you what kind of library this is going to be. There will also be quite a strong presumption against making significant code changes unless it seems absolutely necessary, especially any that break existing behaviour or APIs.
That is a maintenance policy stated as a design constraint, and it is the right one for a library that sits between application code and a camera pipeline that the operating system vendor still changes. Every API you depend on is an API you will never have to migrate from, and the cost is that a genuinely better interface cannot be introduced without a major version.
The licence is BSD-2-Clause, the package is named `picamera2` at version 0.3.38, and it requires Python 3.9 or newer. The classifier says Development Status 4 - Beta, Operating System POSIX Linux, and the topic is Multimedia, Graphics, Capture, Digital Camera.
The list of systems it will not run on is the important part
The support matrix in the documentation is unusually explicit, and it is worth reading as a set of instructions rather than as a list of limitations.
Picamera2 is only supported on Raspberry Pi OS Bullseye or later images, both 32 and 64-bit. It works on all Raspberry Pi boards right down to the Pi Zero, although performance in some areas may be worse on less powerful devices.
And it is not supported on images based on Buster or earlier releases, on Raspberry Pi OS Legacy images, or on Bullseye or later images where the legacy camera stack has been re-enabled.
That third exclusion is the one that catches people, and it is a direct consequence of the architecture. The legacy stack and libcamera are two different kernel interfaces to the same hardware, and an image with the legacy stack re-enabled is a system where the two coexist in a state the library has not been built for. Enabling the legacy option in `raspi-config` to run an old Picamera script will break a Picamera2 script on the same machine, which is the sort of thing that costs a weekend.
The installation advice follows from this. On systems where Picamera2 is supported but not pre-installed, you can install it with:
sudo apt install python3-picamera2 --no-install-recommendswhich gives a slightly reduced installation with fewer of the window system related elements and would be suitable for installing on a Raspberry Pi OS Lite system, or:
sudo apt install python3-picamera2for a full installation.
The `--no-install-recommends` split is the practical detail for a headless Pi. A camera on a kiosk or a robot does not need the desktop integration pieces, and on a Pi Zero the disk saving is worth having.
Since September 2022, Picamera2 is pre-installed on Raspberry Pi OS images, but not on Raspberry Pi OS Lite images. And Picamera2 can be installed using `pip`, however the documentation recommends installing through `apt` as this guarantees you will get versions of Picamera2 and the underlying libcamera libraries that have been confirmed as working together.
That recommendation is the point of the whole paragraph. The library and the camera pipeline underneath it are versioned and shipped together by the OS, so a pip install of a newer Picamera2 on top of an older libcamera is exactly the combination that breaks.
The dependency list describes what a camera library has to do
The runtime dependencies in the package manifest are worth reading as a specification, because they are the actual work of a camera library rather than the interesting part.
`numpy` is the frame buffer layer, and it is the dependency that decides the shape of your code, because a frame from a Raspberry Pi sensor arrives as a numpy array and everything downstream is array arithmetic. `pillow` handles images, and `simplejpeg` handles JPEG encoding, which is a hardware-assisted path on the Pi rather than a software one. `videodev2` is the Video4Linux2 interface, which is the path for the parts of the pipeline that are not libcamera's business. `python-prctl` gives process control, which in this context means the control over how the camera's buffers are allocated and shared.
The archive and format libraries are the ones that surprise people. `libarchive-c` and `OpenEXR` are for reading and writing formats that a camera pipeline has to accept or produce but that a generic imaging library does not. `PiDNG` is for DNG, the raw format that many camera workflows exchange. `piexif` is for EXIF metadata, and `jsonschema` is there to validate that metadata against a schema, which is a small thing that prevents a malformed file from being written out.
`av` is the PyAV binding, which gives access to the FFmpeg libraries underneath, and `tqdm` is a progress bar, which tells you that some of these operations are slow enough that the library offers you a way to see how far along they are.
There is also an optional `gui` extra with `pyopengl` and `PyQt5`, and that maps onto the Qt examples in the separate examples repository, and onto the per-file lint exemptions in the ruff configuration, which name `qt.py`, `gl_helpers.py`, `q_gl_picamera2.py` and `q_gl_picamera2_wl.py` and the direct variant as files that need relaxed rules because they mix import styles and module level state.
That last detail is a small sign of the library's shape. There is a QGL widget path, a GL helper module, and a direct widget variant, which means the library carries a Qt and OpenGL surface for the cases where you want to display the camera preview inside a Qt application rather than save frames to disk. That is the kind of feature that explains the `pyopengl` and `PyQt5` extra existing at all.
Where the code and the tests actually live
The repository layout is small and it tells you something about how the project is organised.
The top level has a `picamera2/` directory holding the package itself, a `tools/` directory, a `pyproject.toml`, a `pyrightconfig.json`, a `requirements-test.txt`, a `CHANGELOG.md` and a `.pre-commit-config.yaml`.
But the tests and the examples are not here. The documentation points at a separate repository, picamera2-examples, which holds the examples, some further Qt application examples and the automated test suite. The tests can be run using its `run_tests.py` script, and `run_tests.py --help` gives more information.
The reasoning is a repository split with a purpose. The main branch of this repository corresponds to the currently released version of Picamera2 so that the examples there can be referred to by users, while development for forthcoming releases happens on the `next` branch. If the examples and the test suite lived in the released branch, then every user reading the documentation would be looking at examples that do not match the version they have installed.
That is a good reason to split, and it has a cost that the project accepts: the test suite for a change to the library lives in a different repository, so a contributor has to move between them.
The `pyrightconfig.json` at the root is worth noticing, because it means the project is type checked with pyright in addition to being linted with ruff, and the dependency list in the manifest explains the surface of the library itself. The runtime dependencies are numpy, PiDNG, piexif, pillow, simplejpeg, videodev2, python-prctl, av, libarchive-c, tqdm, jsonschema and OpenEXR.
Read them as a description of what a camera library has to do. numpy for the frame buffers. pillow for images. simplejpeg for JPEG encoding. videodev2 for the Video4Linux2 path. python-prctl for process control. av for the PyAV bindings. libarchive-c and OpenEXR for reading and writing exotic formats. PiDNG, piexif and jsonschema for DNG handling and EXIF metadata. And tqdm for progress bars, which tells you that some of these operations are slow enough to need one.
There is also an optional `gui` extra with pyopengl and PyQt5, which is the toolkit used by the Qt examples.
How to contribute, and why the commit rules are so specific
The contributing section is long, and almost all of it is about how to structure a pull request. That is unusual, and it is a signal about the project's priorities.
The rules are these. Restricted to one change or feature each, and please try to avoid drive-by fixes especially in a larger set of changes, as it can make them harder to review. The commit history should consist of a number of commits that are as easy to review as possible: where one commit is fixing errors in an earlier commit in the set, please simply merge them, and where a commit is reverting a commit from earlier in the set, please remove the commit entirely, and please avoid adding merge commits or any other unnecessary commits. The commit message should have a short single line at the top which is nonetheless as descriptive as possible, after that more lines explaining in a little more detail exactly what has been done. In general, we don't need to see all the trials, errors and bug-fixes that went into this change, we only want to understand how it works now. And try to ensure that the automated tests are working after all the commits in the set, to avoid other developers going back to an arbitrary earlier commit and finding that things don't work.
That is a house style, expressed unusually precisely, and each rule maps to a real cost. Drive-by fixes make a review slow because the reviewer has to work out which change is the point. Revert commits make a bisect produce a commit that does not build. A commit history that shows the debugging is fine for the author and useless for the next person.
The last rule of the sequence is the one that decides the technical shape of a change. Where changes are likely to be more involved, or may change public APIs, authors should start a discussion with us first so that we can agree a good way forward. Given the stated presumption against breaking changes, a proposal that changes an API has to win that argument before it is written, and the discussion is where it happens.
Before submitting, all the automated tests must be passing, documentation should be updated accordingly, new examples and tests should be included wherever possible as pull requests against the picamera2-examples repository, and an entry in the change log should be considered.
And then the sign-off. The author of the pull request needs to agree that they are donating the work to this project and to Raspberry Pi Ltd., so that we can continue to distribute it as open source to all our users, indicated by finishing commit messages with a blank line followed by `Signed-off-by: Your Name <[email protected]>`.
The style tooling is pre-commit, installed with `pip3 install pre-commit` and then `pre-commit install`, which installs flake8 in a venv and performs linting of changes prior to committing.
Editorial conclusion
Picamera2 fits a project that has to run on a current Raspberry Pi OS image and wants the camera driven through libcamera rather than the retired legacy stack, because the library wraps the modern pipeline and keeps the API small enough to read. Skip it if you need the old Picamera API, since this is a replacement rather than a compatibility layer, and skip it if your image still has the legacy stack enabled, because the library is explicitly not supported there. Before you install, check the image variant, since it is not pre-installed on Raspberry Pi OS Lite images and it does not run on Buster or earlier or on Legacy images, and note the beta status, since the release notes say significant code changes will be avoided unless absolutely necessary. The last push was on 2026-10-12 with version 0.3.38.
Frequently asked questions
What is Picamera2 and what does it replace?
It is the libcamera based replacement for Picamera, which was a Python interface to the Raspberry Pi's legacy camera stack. Picamera2 also presents an easy to use Python API, and it is BSD-2-Clause licensed at version 0.3.38.
Which Raspberry Pi OS images support Picamera2?
Only Bullseye or later images, both 32 and 64-bit. It is not supported on Buster or earlier, on Raspberry Pi OS Legacy images, or on Bullseye or later images where the legacy camera stack has been re-enabled.
How do I install Picamera2 on a Raspberry Pi OS Lite system?
Use `sudo apt install python3-picamera2 --no-install-recommends` for a reduced installation without the window system elements, or `sudo apt install python3-picamera2` for the full one. The documentation recommends apt over pip because it guarantees matching versions of Picamera2 and libcamera.
Where do the Picamera2 tests live and how do I run them?
The examples and the automated test suite live in the separate picamera2-examples repository, and the tests run with its `run_tests.py` script, whose options are described by `run_tests.py --help`.
What are the rules for contributing to Picamera2?
One change or feature per pull request, a commit history that is easy to review with no drive-by fixes, revert commits removed rather than added, tests passing, documentation updated, and a `Signed-off-by` line agreeing to donate the work to the project and to Raspberry Pi Ltd.
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/raspberrypi-picamera2)Was this useful?