Capture Photos in Ionic with Capacitor Camera Plugin: A Step‑by‑Step Guide
Step‑by‑step guide to adding the Capacitor Camera plugin to an Ionic project, configuring native permissions, capturing a photo, and displaying it safely on iOS and Android.
10 Nov 2026, 11:53 UTC

Desired outcome
Take a picture using the device camera and show it inside an Ionic web view, working on both iOS and Android without writing native code.
Prerequisites
- Node ≥ 18 and npm (or yarn) installed.
- Ionic CLI (
npm i -g @ionic/cli). - An existing Ionic project (Angular, React, or Vue) with
@capacitor/corealready added. - Native tooling: Xcode 15+ for iOS, Android Studio Koala+ with SDK 34 for Android.
- Camera permission keys configured in the native projects (see Permission configuration below).
Permission configuration
iOS
Open ios/App/App/Info.plist and add:
<key>NSCameraUsageDescription</key>
<string>This app needs camera access to capture photos.</string>Android
Edit android/app/src/main/AndroidManifest.xml inside the <manifest> element:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="false" />The required="false" flag lets the app run on devices without a camera (e.g., some tablets) while still requesting the permission when hardware exists.
Focused procedure
- Install the Camera plugin
Run in the project root (wherepackage.jsonlives):npm i @capacitor/camera npx cap syncnpx cap synccopies web assets to each native project and updates the native Gradle / CocoaPods files. It must be run after every plugin install or native config change. - Add a capture button and image placeholder
In an Ionic page component (example uses Angular syntax; adapt for React/Vue):<ion-button (click)="takePhoto()" expand="block">Take photo</ion-button> <ion-img *ngIf="photo" [src]="photo" alt="Captured photo"></ion-img> - Implement the capture logic
import { Camera, CameraResultType, CameraSource } from '@capacitor/camera'; async takePhoto() { try { const image = await Camera.getPhoto({ quality: 90, allowEditing: false, resultType: CameraResultType.Uri, // returns a safe file:// or capacitor:// URI source: CameraSource.Camera }); // image.webPath is a URL the web view can render directly this.photo = image.webPath; } catch (err) { // Handle permission denial, no camera hardware, or user cancel console.error('Camera error', err); this.handleCameraError(err); } }Using
CameraResultType.Uriavoids loading large base‑64 strings into memory. If you need a base‑64 string (e.g., for upload), switch toCameraResultType.Base64and be aware of the memory impact. - Run on a device or emulator
Open the native IDEs:npx cap open ios # opens Xcode npx cap open android # opens Android StudioBuild and run on a physical device (recommended) or an emulator/simulator that has a camera backend.
Expected checks
- The
Camera.getPhotopromise resolves with an object containingwebPath(orbase64String). - The
<ion-img>renders the captured photo without CORS or mixed‑content warnings. - At runtime the system permission dialog appears on first use; subsequent calls use the granted state.
npx cap syncfinishes with no errors, and the native builds succeed in Xcode / Android Studio.
Recovery options
Permission denied
If the user taps “Don’t Allow”, the promise rejects with a PERMISSION_DENIED code. Show a friendly toast and provide a button that opens the app’s system settings:
import { openSettings } from '@capacitor/app';
async handleCameraError(err) {
if (err.code === 'PERMISSION_DENIED') {
const confirmed = await this.showSettingsPrompt();
if (confirmed) await openSettings();
}
}No camera hardware
On devices lacking a camera, Camera.getPhoto rejects with NOT_SUPPORTED. Offer a file‑picker fallback using CameraSource.Photos or the Capacitor Filesystem picker.
Sync failures
If npx cap sync reports missing pods or Gradle errors:
1. Delete node_modules, ios/App/Pods, android/app/build.
2. Run npm ci (or npm install).
3. Run npx cap sync again.
This clean‑reinstall resolves most version‑mismatch issues.
Limitations & practical verification
- Browser fallback: The Capacitor Camera plugin does not provide a camera UI in a plain desktop browser. For progressive‑web‑app testing, implement a fallback that uses
navigator.mediaDevices.getUserMediaand a canvas capture. - Memory: Base64 results can exceed 10 MB for high‑resolution photos, risking out‑of‑memory crashes on low‑end devices. Prefer
CameraResultType.Uri(file URI) for display and only convert to base64 when uploading. - Orientation: The returned URI respects EXIF orientation on iOS; on Android you may need to read the EXIF tag and rotate via CSS or canvas if the image appears sideways.
Verification checklist (run on a physical device):
- Launch the app, tap “Take photo”.
- System camera UI opens; capture a picture.
- App returns to the Ionic page and the image appears instantly.
- Inspect the native console (Xcode log or logcat) – you should see the plugin result object with a
webPathlikecapacitor://localhost/_capacitor_file_/.../IMG_1234.jpg. - Rotate the device; confirm the image orientation stays correct.
If any step fails, consult the native logs for missing permission keys or denied authorization and apply the recovery steps above.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.