Image Metadata Analyzer & Privacy Stripper
Pricing
from $0.02 / actor start
Image Metadata Analyzer & Privacy Stripper
Extract EXIF (GPS, camera, exposure), IPTC (copyright, keywords), XMP (rights, creator) metadata from images. Privacy mode strips all metadata and returns clean base64 image bytes. GPS to human-readable address via reverse geocoding. Supports JPEG, PNG, TIFF, WebP, HEIC/HEIF.
Pricing
from $0.02 / actor start
Rating
0.0
(0)
Developer
Perry AY
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Image Metadata Analyzer & Privacy Stripper — Extract or Remove Hidden Photo Data
Pull every piece of hidden data out of your images — or strip it all away before you share them.
Drop in a JPEG from your phone and you'll see which camera took it, the exact GPS coordinates where you stood, the exposure settings the camera chose, and any copyright notices or captions embedded in the file. Switch to privacy mode and the same image comes back with every trace of metadata surgically removed.
This actor reads EXIF (camera, GPS, exposure), IPTC (copyright, keywords, captions), and XMP (creator, rights, ratings) from JPEG, PNG, TIFF, WebP, and HEIC/HEIF images. No external libraries — just pure Python byte-level parsing.
What does it do?
Every photo you take carries a hidden payload. The phone model, the GPS fix accurate to within metres, the exact timestamp, the lens and aperture settings, and any edit history from software you've opened it in. This data is invisible when you look at the image, but anyone who downloads your file can extract it in seconds.
This actor reads all three major metadata formats:
- EXIF — GPS latitude and longitude, camera make and model, date taken, exposure time, aperture, ISO, focal length, flash status, and orientation
- IPTC — Copyright notice, keywords, captions, byline, and headline from Photoshop and similar editors
- XMP — Creator attribution, usage rights, star ratings, and Dublin Core metadata from Adobe and other modern tools
GPS coordinates can optionally be reverse-geocoded through OpenStreetMap Nominatim to a human-readable address — "123 High Street, Bristol, UK" instead of "51.4545, -2.5879".
For privacy, the actor strips metadata from each format individually. JPEG stripping preserves the orientation tag so your photo doesn't rotate sideways. PNG stripping removes tEXt/iTXt/zTXt chunks. WebP stripping removes EXIF/XMP chunks. HEIC stripping attempts to remove the metadata track from the MOOV box. TIFF stripping is best-effort due to the format's variability.
Three modes:
- Extract — Pull everything: EXIF, IPTC, XMP, GPS address, dimensions, file size, and colour mode
- Strip — Wipe all metadata markers and return a clean base64-encoded version
- Both — Extract the metadata first, then strip and return the clean version alongside it
Features
- EXIF extraction — GPS coordinates (latitude, longitude, altitude), camera make and model, date and time taken, exposure time, F-number, ISO speed, focal length, flash status, and image orientation
- GPS reverse geocoding — Optional Nominatim lookup converts raw coordinates into a street-level address
- IPTC extraction — Copyright notice, keywords, caption/description, byline, headline, and category/supplemental category fields
- XMP extraction — Creator attribution, usage rights, star rating, and Dublin Core metadata (title, description, date)
- Format-aware stripping — Separate strip logic per format: JPEG (orientation preservation), PNG (text chunk removal), WebP (EXIF/XMP chunk removal), HEIC (MOOV metadata track removal), TIFF (best-effort)
- Format detection — Magic-byte detection for all five supported formats
- Dimension extraction without decoding — Reads width and height directly from binary headers for JPEG (SOF marker), PNG (IHDR chunk), WebP (VP8/VP8L/VP8X), TIFF (ImageWidth/ImageLength tags), HEIC (ISO BMFF header)
- Batch processing — Up to 50 images per run, 5 concurrent downloads via asyncio semaphore
- Per-image isolation — One image failing to download or parse doesn't affect the rest of the batch
Who is it for?
| Persona | What they use it for |
|---|---|
| Photographer | Checking EXIF data on client work to confirm camera settings and shooting conditions |
| Security researcher | Auditing images shared online for leaked GPS coordinates and device serial numbers |
| Developer | Integrating metadata extraction into content pipelines, CMS uploads, or image processing workflows |
| Privacy-conscious user | Stripping location and camera data before sharing photos on social media or forums |
| Digital asset manager | Indexing image libraries by copyright, keywords, and creation date from IPTC and XMP fields |
| Journalist | Verifying the provenance of images — camera, date, software edit history — before publication |
Input Parameters
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
images | array | Yes | — | List of image URLs or data URIs to process. Max 50. |
mode | enum | No | extract | extract, strip, or both |
include_gps | boolean | No | true | Reverse-geocode GPS coordinates to a street address via Nominatim |
strip_preserve_orientation | boolean | No | true | When stripping, keep the orientation tag so the image doesn't rotate |
Example Input
Extract all metadata from an image
{"images": ["https://example.com/photos/vacation.jpg"],"mode": "extract","include_gps": true}
Strip metadata for privacy
{"images": ["https://example.com/photos/selfie.jpg", "https://example.com/screenshots/dashboard.png"],"mode": "strip","strip_preserve_orientation": true}
Extract then strip (full transparency + clean file)
{"images": ["https://example.com/uploads/portrait.heic"],"mode": "both","include_gps": false}
Output Format
Each item in the dataset corresponds to one input image.
| Field | Type | Description |
|---|---|---|
filename | string | Filename extracted from the URL or inline.<fmt> for data URIs |
format | string | Detected format: JPEG, PNG, TIFF, WebP, HEIC |
width | integer / null | Width in pixels |
height | integer / null | Height in pixels |
file_size_bytes | integer | Size of the downloaded image in bytes |
color_mode | string / null | Detected colour mode (RGB, RGBA, Grayscale, CMYK, Lab, or unknown) |
exif | object / null | EXIF data: camera_make, camera_model, date_taken, exposure, aperture, iso, focal_length, flash, orientation, gps_lat, gps_lon, gps_altitude |
iptc | object / null | IPTC data: copyright, keywords, caption, byline, headline, category, supplemental_category |
xmp | object / null | XMP data: creator, rights, rating, dc_title, dc_description, dc_date |
gps_address | string / null | Human-readable address from reverse geocoding (only when include_gps is true) |
stripped_image | string / null | Base64-encoded clean image bytes (only in strip or both mode) |
has_gps | boolean | Whether GPS coordinates were found in the EXIF data |
warnings | array | Non-fatal warnings (fetch failures, unknown format, corrupt EXIF entries) |
error | string / null | Fatal error for this image (fetch failure, processing crash with traceback) |
Example output (extract mode)
{"filename": "vacation.jpg","format": "JPEG","width": 4032,"height": 3024,"file_size_bytes": 2847612,"color_mode": "RGB","exif": {"camera_make": "Apple","camera_model": "iPhone 15 Pro","date_taken": "2024-06-15T14:22:31","exposure": "1/120","aperture": "f/1.8","iso": 80,"focal_length": "6.8mm","flash": "No Flash","orientation": 1,"gps_lat": 51.4545,"gps_lon": -2.5879},"iptc": {"copyright": "© 2024 Example Photographer","keywords": ["vacation", "summer", "beach"],"caption": "Sunset at the harbour"},"xmp": null,"gps_address": "Princes Wharf, Wapping Road, Spike Island, Bristol, City of Bristol, West of England, England, BS1 4RN, United Kingdom","has_gps": true,"stripped_image": null,"warnings": [],"error": null}
FAQ
Q: Which image formats are supported? A: JPEG, PNG, TIFF, WebP, and HEIC/HEIF. Format detection uses magic bytes at the start of the file, not file extensions.
Q: Does GPS reverse geocoding cost extra?
A: Reverse geocoding uses the OpenStreetMap Nominatim API. It is only performed when include_gps is true and the image actually contains GPS data.
Q: What happens if stripping fails on a particular format? A: The stripped image field will be null but all other metadata fields will still be populated. The image is never modified in-place — the original bytes are always available through the extraction fields.
Q: Can this handle images larger than 20 MB? A: No. Images exceeding 20 MB are skipped with a warning. This prevents memory issues when processing very large files.
Q: Is the base64 output from stripping suitable for embedding in HTML?
A: Yes. The base64 output is standard and can be used directly in data: URIs or HTML src attributes.
Q: Does stripping preserve image quality? A: Yes. Stripping only removes metadata markers from the binary structure — the actual pixel data is never touched. The image quality is identical to the original.
Q: How is orientation handled when stripping?
A: JPEG stripping preserves the EXIF orientation tag so the image displays correctly after stripping. Set strip_preserve_orientation to false if you want the orientation tag removed as well (the image may rotate in viewers that honour it).
API Usage
cURL
curl -X POST "https://api.apify.com/v2/acts/perryay~image-metadata-analyzer/runs?token=YOUR_API_TOKEN" \-H "Content-Type: application/json" \-d '{"images": ["https://example.com/photo.jpg"],"mode": "extract","include_gps": true}'
Python
from apify_client import ApifyClientclient = ApifyClient("YOUR_API_TOKEN")run = client.actor("perryay~image-metadata-analyzer").call(run_input={"images": ["https://example.com/photo.jpg"],"mode": "extract","include_gps": True,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["exif"]["camera_model"]) if item.get("exif") else None
Node.js
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });const run = await client.actor('perryay~image-metadata-analyzer').call({images: ['https://example.com/photo.jpg'],mode: 'extract',include_gps: true,});const dataset = client.dataset(run.defaultDatasetId);for await (const item of dataset.iterateItems()) {console.log(item.format, item.width, '×', item.height);}
Use Cases
- Stripping GPS coordinates from photos before sharing them on social media or public forums
- Auditing your own website to check if uploaded images leak device serial numbers or location data
- Building a privacy-first image upload pipeline that automatically scrubs metadata on ingestion
- Indexing a photo library by camera model, date taken, and copyright holder from EXIF and IPTC
- Verifying the provenance of images submitted by sources — does the camera and timestamp match the story?
- Extracting GPS coordinates from field photos and reverse-geocoding them to addresses for reports
- Generating clean, metadata-free thumbnails for public-facing product images
- Processing batch submissions from users who want to share photos but don't know what metadata their phone embeds