diff --git a/src/py/libcamera/py_main.cpp b/src/py/libcamera/py_main.cpp
index d0ef6915b..3b101f996 100644
--- a/src/py/libcamera/py_main.cpp
+++ b/src/py/libcamera/py_main.cpp
@@ -34,6 +34,7 @@ LOG_DEFINE_CATEGORY(Python)
 
 }
 
+#if PYBIND11_VERSION_MAJOR < 3
 /*
  * This is a holder class used only for the Camera class, for the sole purpose
  * of avoiding the compilation issue with Camera's private destructor.
@@ -79,6 +80,13 @@ private:
 
 PYBIND11_DECLARE_HOLDER_TYPE(T, PyCameraSmartPtr<T>)
 
+using PyCameraHolder = PyCameraSmartPtr<Camera>;
+using PyCameraArg = PyCameraSmartPtr<Camera>;
+#else
+using PyCameraHolder = py::smart_holder;
+using PyCameraArg = std::shared_ptr<Camera>;
+#endif
+
 /*
  * Note: global C++ destructors can be ran on this before the py module is
  * destructed.
@@ -103,7 +111,7 @@ PYBIND11_MODULE(_libcamera, m)
 	 */
 
 	auto pyCameraManager = py::class_<PyCameraManager, std::shared_ptr<PyCameraManager>>(m, "CameraManager");
-	auto pyCamera = py::class_<Camera, PyCameraSmartPtr<Camera>>(m, "Camera");
+	auto pyCamera = py::class_<Camera, PyCameraHolder>(m, "Camera");
 	auto pySensorConfiguration = py::class_<SensorConfiguration>(m, "SensorConfiguration");
 	auto pyCameraConfiguration = py::class_<CameraConfiguration>(m, "CameraConfiguration");
 	auto pyCameraConfigurationStatus = py::enum_<CameraConfiguration::Status>(pyCameraConfiguration, "Status");
@@ -347,7 +355,7 @@ PYBIND11_MODULE(_libcamera, m)
 		.def("range", &StreamFormats::range);
 
 	pyFrameBufferAllocator
-		.def(py::init<PyCameraSmartPtr<Camera>>(), py::keep_alive<1, 2>())
+		.def(py::init<PyCameraArg>(), py::keep_alive<1, 2>())
 		.def("allocate", [](FrameBufferAllocator &self, Stream *stream) {
 			int ret = self.allocate(stream);
 			if (ret < 0)
