cordova-plugin-camera: the plugin that tells you it may be unnecessary
Apache Cordova Plugin camera
At a glance
- What is it?
- cordova-plugin-camera exposes a navigator.camera API for taking and selecting images in a Cordova app on Android, iOS and the browser. Its own documentation opens by recommending the web platform's file input with a capture attribute instead, and the rest of the readme is about the permission and platform configuration you inherit if you do install it.
- Who is it for?
- cordova-plugin-camera is the right choice for a Cordova app that needs camera capture features the web platform does not expose, such as saving to the photo album, or that already has a native camera workflow it needs to match. It is the wrong choice for the ordinary case of letting a user pick or take a picture, where the readme itself points you at a file input element.
- Can I use it commercially?
- Yes. Apache-2.0 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 11 days ago.
- What is it written in?
- Mainly Objective-C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The first thing the readme says is that you may not need it
The note at the top of the readme is unusual and worth quoting in substance. Depending on your use case, this plugin may be unnecessary, and the project strongly recommends using the WebView's native file input element with an image accept type and the capture attribute before opting for the plugin. The example demonstrates capturing an image, and if you only need to select an existing image, you simply remove the capture attribute. The links point at the web platform documentation for the element, for the accept attribute and for the capture attribute.
The plugin is then described as appropriate for advanced use cases.
That framing tells you exactly how to evaluate this project. If your requirement is a user tapping a button and either taking a photo or choosing one, the modern web platform in the Cordova WebView can do it with no plugin, no permissions and no native code. The plugin earns its place when you need something the web API does not offer, and the examples of that in the documentation are the permission-sensitive paths: saving to the photo album, and the platform specific behaviours that come with a native camera workflow.
The rest of this article is about what the plugin does once you have decided you need it, because the configuration it requires is substantial and the failure modes are sharp.
navigator.camera, and the deviceready gate
The plugin defines a global navigator.camera object, which provides an API for taking pictures and choosing images from the device image library.
The important detail, and the one that catches people, is that although the object is attached to the global navigator object, it is not available until after the deviceready event. The readme's own example is the canonical shape of the fix:
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
console.log(navigator.camera);
}This is a general Cordova property rather than a quirk of the camera plugin. The WebView loads your JavaScript before the native side of the application is ready, so any plugin API touched at the top level of a script may be undefined. The camera plugin inherits that constraint, and because the object is on the global navigator, code that assumes it is always there will fail in a way that looks like a missing plugin rather than a timing problem.
The supported platforms are Android, the browser and iOS, and the browser platform is worth a second look for anyone testing locally, because a Cordova app that behaves differently in a desktop browser than on a device is a common source of confusion, and the presence of a browser implementation means the plugin is expected to work in that environment too.
Plugin variables exist because of a shared Android dependency
Plugin variables let you configure parts of a plugin, and they must be set at installation time, by appending a variable assignment to the plugin add command. If you want to change or remove any of them, the documentation says to uninstall and reinstall with the updated variables, which is a sharp edge worth knowing before you set one.
There is currently one variable, and it exists for a very specific reason. ANDROIDX_CORE_VERSION configures the androidx.core dependency for this plugin only. The explanation is that some plugins include this dependency with hard-coded versions, so this variable lets you try to match those versions and reduce conflicts.
cordova plugin add cordova-plugin-camera --variable ANDROIDX_CORE_VERSION=1.8.0The default is 1.6.+, so the plugin declares a floating minor version of the AndroidX core library, and the variable lets you pin it to something specific when another plugin in the same application is pulling a different one.
This is the kind of configuration that only exists because of a shared dependency graph, and it is worth understanding rather than copying blindly. If you have a single plugin application, the default is fine. If you have several plugins that each want a different version of the same AndroidX artifact, this variable is how you align them, and the install-then-reinstall rule is the price of a build-time setting in a system where plugin configuration is recorded at install time.
The Android storage permission only matters up to API 28
The Android configuration section is short, and it is conditional in a way that saves a lot of unnecessary manifest editing.
If you support Android 9, which is API 28, and lower, and you need the saveToPhotoAlbum option, then the step is required. If you support only Android 10, which is API 29, and later, or you do not need saveToPhotoAlbum, you skip it entirely. Configuring the WRITE_EXTERNAL_STORAGE permission for Android 10 or later has no effect, which is stated explicitly so that people do not add a permission that does nothing.
When it is needed, it is added to the manifest through the config-file tag in the app's config.xml:
<config-file target="AndroidManifest.xml" parent="/*" xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
</config-file>The maximum SDK version attribute is the mechanism that makes this safe. It caps the permission at the API level where it is actually needed, so on a newer device the permission is not granted and the modern scoped storage model applies instead.
That is the shape of the whole plugin, incidentally. Most of the configuration is not about the camera, it is about the platform permission systems that changed underneath it, and a plugin that has been around for many years accumulates this kind of conditional documentation.
iOS usage descriptions, and a crash before the dialog
The iOS section is the one that will bite you hardest, because the failure is a crash rather than a permission denial.
Since iOS 10, you must provide usage descriptions in the info.plist when accessing privacy sensitive data, and the required keys depend on how you use the plugin and which iOS versions you support. The camera key is required whenever the camera is used. The photo library read key is required only when your app runs on iOS 13 or older and uses the photo library as the source type, because on iOS 14 and later the plugin uses the PHPicker for read-only access, which does not need it. The photo library add key is required when the plugin writes to the user's library, and the location key is required if the CameraUsesGeolocation setting is enabled.
The consequence of getting this wrong is stated in the clearest terms in the whole document. If you do not provide the required usage description, the app will crash before showing the dialog. And Apple will reject apps that access private data but do not provide a usage description, so this is both a runtime failure and a review failure.
The strings are added through the edit-config tag in config.xml, with a merge mode so that a platform file is modified rather than replaced:
<edit-config target="NSCameraUsageDescription" file="*-Info.plist" mode="merge">
<string>need camera access to take pictures</string>
</edit-config>The wildcard in the file name is what makes it apply across the platform configurations, and the merge mode is what lets several edit-config entries each add one key without overwriting each other.
The dependency matrix says which Cordova versions work
The manifest carries a table of Cordova dependencies, and it is a more useful piece of documentation than most plugin manifests manage.
The structure maps each plugin version to the minimum Cordova platform versions it needs. Plugin 3.0.0 required cordova-android 6.3.0 or later. Plugin 4.1.0 required the same for Android plus Cordova 7.1.0 or later. Plugin 5.0.0 raised the Android floor to 9.0.0 and introduced a cordova-ios floor of 5.1.0. Plugin 6.0.0 raised Android to 10.0.0, and 7.0.0 raised it to 12.0.0 while keeping iOS at 5.1.0. Plugin 8.0.0 kept the same floors, and 9.0.0 raised the iOS requirement to 7.0.0. Plugin 10.0.0 then lists only Cordova itself with a requirement above 100.
Reading that table tells you two things. The Android floor moved up faster than the iOS one, which reflects the AndroidX transition in the platform toolchain. And the last entry is unusual, listing a Cordova version above 100, which reads as a placeholder for a future major rather than a number anyone can satisfy today.
The package version itself is 9.0.0-dev, so the development line is a major version ahead of the last stable, and the npm badge tracks the latest published release while the git badge tracks development. The plugin is published for the android, ios and browser platforms in the manifest, and the keywords confirm the same three.
For an application that supports a wide range of Cordova versions, the table is the document to read first, because a plugin that requires cordova-ios 7.0.0 cannot go into a project still on Cordova 5.
An Apache project with no tagged releases
The administrative side of the repository is what tells you this is a foundation project rather than a community package.
There is an .asf.yaml file, which is the Apache Software Foundation's own project descriptor, and an .asf-release directory for the release process, alongside a NOTICE file, a LICENSE file, a licence_checker.yml configuration, a .rat-excludes file for the release audit tooling, and separate CONTRIBUTING and DEVELOPMENT documents. The release audit has its own workflow badge, next to the Android, Chrome and iOS build workflows and a lint workflow.
The code layout follows the Cordova plugin conventions, with a plugin.xml describing the plugin, a www directory holding the JavaScript that runs in the WebView, a src directory with the native implementations, a types directory with a TypeScript declaration entry point, and a tests directory.
The package is minimal by design. The only dependency is the shared ESLint configuration, and the scripts are lint, lint with fix, and a test script that runs the linter. There is no test framework and no build step in the npm scripts, which is consistent with a Cordova plugin where the real testing happens in the platform workflows against a Cordova app.
The licence is Apache-2.0, the author is the Apache Software Foundation, and the default branch is master. There are no GitHub releases, so the npm published version is the artefact to track, and the last push was on 2026-08-20 with the repository not archived. The types entry point is worth noting for TypeScript users, since the plugin ships its own declarations rather than leaving the API untyped.
Editorial conclusion
cordova-plugin-camera is the right choice for a Cordova app that needs camera capture features the web platform does not expose, such as saving to the photo album, or that already has a native camera workflow it needs to match. It is the wrong choice for the ordinary case of letting a user pick or take a picture, where the readme itself points you at a file input element. Before you install it, decide whether the web platform covers your case, check the Cordova dependency table for your platform versions, and read the platform permission sections in full, because a missing usage description crashes the iOS app before the permission dialog even appears.
Frequently asked questions
Do I need the cordova-plugin-camera plugin to take a photo in an app?
Probably not. The plugin's own readme strongly recommends the WebView's native file input element with an image accept type and the capture attribute, and says that removing the capture attribute turns it into a picker for an existing image. The plugin is positioned for advanced use cases that the web platform does not cover.
Why is navigator.camera undefined in my Cordova app?
Because the object is not available until after the deviceready event, even though it is attached to the global navigator object. Add a listener for deviceready and use the camera API from inside that handler, which is what the plugin's own example does.
Which iOS usage descriptions does cordova-plugin-camera require?
The camera key is required whenever the camera is used, the photo library add key when the plugin writes to the library, the location key if CameraUsesGeolocation is enabled, and the photo library read key only for iOS 13 and older, because iOS 14 and later use the PHPicker for read-only access. If a required description is missing, the app crashes before showing the permission dialog and Apple rejects the app.
What does the ANDROIDX_CORE_VERSION plugin variable do?
It configures the androidx.core dependency for this plugin only, so it can be matched against the version another plugin hard-codes and reduce conflicts. The default is 1.6.+, and because plugin variables are set at install time, changing one means uninstalling and reinstalling the plugin.
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/apache-cordova-plugin-camera)Was this useful?