Camera Access in Development: HTTPS Setup Guide
2025-10-06
Camera Access in Development: HTTPS Setup Guide
Modern browsers require HTTPS for camera access due to security policies. Here's how to enable camera access when developing the MTG card scanner locally.
The Problem
When running npm run dev
and trying to use the camera scanner, you see errors like:
- β "Camera access is not supported"
- π "NotAllowedError: Permission denied"
- β οΈ "getUserMedia is not defined"
- π« "Camera requires HTTPS"
This happens because browsers block camera/microphone access on non-HTTPS connections (except localhost on some browsers).
The Solution
Option 1: Run Development Server with HTTPS (Recommended)
Next.js 14.2+ includes experimental HTTPS support. Use the new dev:https
script:
npm run dev:https
This will:
- Start Next.js development server with HTTPS enabled
- Auto-generate a self-signed certificate
- Allow camera access in your browser
First time setup:
When you visit https://localhost:3000
, your browser will show a certificate warning because it's self-signed. This is normal and safe for local development.
Chrome/Edge:
- Click "Advanced"
- Click "Proceed to localhost (unsafe)"
Firefox:
- Click "Advanced"
- Click "Accept the Risk and Continue"
Safari:
- Click "Show Details"
- Click "visit this website"
Option 2: Use localhost (Limited Support)
Some browsers allow camera access on http://localhost
(but not http://127.0.0.1
or other IPs):
npm run dev
# Visit http://localhost:3000 (not 127.0.0.1)
This works on:
- β Chrome/Edge on localhost
- β Firefox on localhost
- β Safari (requires HTTPS even for localhost)
- β Mobile browsers (require HTTPS)
Option 3: Upload Images Instead
The scanner supports both camera capture AND image upload. Use the file upload button if camera access isn't working:
- Take a photo of your card with your phone
- Click "π Upload Image" in the scanner
- Select the photo from your device
Enhanced Error Messages
The scanner now provides specific guidance based on the error:
// Permission denied
β Camera permission denied. Please allow camera access in your browser.
// No camera hardware
π· No camera found. Please connect a camera or upload an image.
// HTTPS required
π Camera requires HTTPS. In development, run: npm run dev:https
// Generic error
Could not access camera. Please check permissions or upload an image.
Testing on Mobile Devices
To test the camera on your phone during development:
1. Use ngrok for HTTPS Tunneling
# Install ngrok
npm install -g ngrok
# Start your dev server
npm run dev
# In another terminal, create HTTPS tunnel
ngrok http 3000
Visit the https://
URL ngrok provides on your mobile device.
2. Use Your Local Network with HTTPS
# Run with HTTPS
npm run dev:https
# Find your local IP
ipconfig # Windows
ifconfig # Mac/Linux
# Visit from mobile
https://192.168.1.XXX:3000
Accept the certificate warning on your mobile device.
Browser Camera Permissions
Granting Camera Access
Chrome/Edge:
- Click the camera icon in the address bar
- Select "Always allow https://localhost to access your camera"
- Reload the page
Firefox:
- Click the camera icon in the address bar
- Select "Allow" and check "Remember this decision"
- Reload the page
Safari:
- Safari β Settings β Websites β Camera
- Find "localhost" and set to "Allow"
Revoking Camera Access (to Test Errors)
Chrome/Edge:
- Settings β Privacy and security β Site settings β Camera
- Find localhost and change to "Block"
Firefox:
- about:preferences#privacy β Permissions β Camera β Settings
- Remove localhost or set to "Block"
Production Considerations
In production behind Caddy/nginx with proper SSL certificates, camera access works automatically because:
- β Domain has valid SSL certificate
- β Browser trusts the certificate
- β HTTPS connection is secure
- β Camera API is fully supported
The dev:https
script is ONLY needed for local development.
Technical Details
How the HTTPS Dev Server Works
Next.js's --experimental-https
flag:
// Internally generates
{
key: fs.readFileSync('.next/key.pem'),
cert: fs.readFileSync('.next/cert.pem')
}
Certificates are auto-generated on first run and cached in .next/
directory.
Browser Security Policy
The MediaDevices API requires a "secure context":
// This only works in secure contexts
navigator.mediaDevices.getUserMedia({ video: true })
Secure contexts are:
- β HTTPS pages (any domain)
- β
http://localhost
(Chrome/Firefox only) - β
http://127.0.0.1
(Chrome/Firefox only) - β HTTP pages (any other domain/IP)
- β File:// protocol
Error Detection in Code
The scanner detects specific camera errors:
try {
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
} catch (err) {
if (err.name === 'NotAllowedError') {
// User denied permission
} else if (err.name === 'NotFoundError') {
// No camera hardware
} else if (err.name === 'NotSupportedError') {
// HTTPS required
}
}
Troubleshooting
"Camera still doesn't work after npm run dev:https"
- Check the URL: Must be
https://localhost:3000
nothttp://
- Clear permissions: Revoke and re-grant camera access
- Restart browser: Sometimes permissions are cached
- Try another browser: Chrome/Edge have best support
"Certificate error won't go away"
This is normal for self-signed certificates. You must manually bypass the warning:
- Click "Advanced" or "Show Details"
- Click "Proceed" or "Accept Risk"
- You only need to do this once per session
"Camera works but quality is poor"
The scanner requests high resolution:
video: {
facingMode: 'environment', // Back camera on mobile
width: { ideal: 1600 },
height: { ideal: 1200 }
}
If your camera doesn't support this resolution, it will use the highest available.
"Mobile camera shows front-facing instead of back"
Some devices don't properly support facingMode: 'environment'
. You can switch cameras using the browser's camera switcher icon (usually in the address bar).
Development Workflow
Recommended workflow:
# Terminal 1: Run dev server with HTTPS
npm run dev:https
# Terminal 2: Watch for file changes (optional)
# Your editor's auto-save will trigger hot reload
# Browser: Visit https://localhost:3000/scan
# Accept certificate warning (first time only)
# Test camera scanner
For rapid iteration without camera:
# Use regular dev server
npm run dev
# Test with image uploads instead of camera
# Upload sample card images from your collection
Summary
Method | Camera Access | Mobile | Setup |
---|---|---|---|
npm run dev:https |
β Yes | β Yes (with IP) | Accept self-signed cert |
npm run dev on localhost |
β οΈ Limited | β No | Chrome/Firefox only |
Upload image | β Works | β Works | No setup needed |
Production (HTTPS) | β Yes | β Yes | Real SSL cert |
For the best development experience testing the camera scanner, use npm run dev:https
.
Additional Resources
Camera access is essential for the ID scanner-style card positioning guide. Following this setup ensures you can test the full scanner experience during development.