Image Metadata & EXIF Extractor: GPS, Camera, Colors, Hash
Pricing
from $3.50 / 1,000 analyzed images
Image Metadata & EXIF Extractor: GPS, Camera, Colors, Hash
Read image metadata in bulk: EXIF camera and lens, exposure settings, date taken, GPS location with map link, size, color profile, dominant colors and perceptual hashes to find near-duplicates. Image URLs or a dataset column in. Failed images are free.
Pricing
from $3.50 / 1,000 analyzed images
Rating
0.0
(0)
Developer
Charles Markette
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Image Metadata & EXIF Extractor reads the metadata of images in bulk and returns one row per image. Each row has the camera, lens and exposure settings, the date taken (with its timezone when the camera recorded one), the GPS location in decimal degrees with a Google Maps link, and the author, copyright, title, description and keywords from EXIF, XMP, IPTC or PNG text. It also gives size, format, orientation, DPI and colour profile, the dominant colours, a SHA-256 and three perceptual hashes (aHash, pHash, dHash), and can find near-duplicates. Paste image URLs, or point it at any Apify dataset with image links, and the columns are added next to each item.
Why this Actor
- Readable fields, not a tag dump. GPS degrees/minutes/seconds become signed decimal
lat/lon(south and west are negative). Exposure becomes"1/250", the flash code becomes"Auto, fired", and the date becomes ISO 8601. If you want every tag, turn on All EXIF tags (raw). - Honest dates. EXIF dates are the camera's local time with no timezone.
dateTakenis that local time.dateTakenUtcis only filled when the file records its offset (EXIFOffsetTimeOriginal, or an XMP date with a timezone). It is never guessed. - Descriptive metadata from every common place. Author and copyright are read from EXIF
Artist/Copyright, then XMP (dc:creator,dc:rights,dc:title,dc:description,dc:subject), then IPTC (By-line, Copyright Notice, Object Name, Caption, Keywords), then PNG text chunks. Keywords are merged from all of them. - Find duplicates and re-uploads.
sha256finds exact copies.pHashalso matches copies that were resized, re-compressed or lightly edited. With Find near-duplicates, each row says which earlier image it looks like, and the run summary lists every group. - Privacy-minded. Camera and lens serial numbers, the camera owner's name and the binary MakerNote are never output. GPS location can be switched off, which removes the coordinates everywhere, including the raw EXIF.
- Safe with untrusted URLs. Private, loopback, link-local and cloud-metadata addresses are refused, on every redirect hop too. Downloads are capped at 50 MB, and images are size-checked from their header before any pixels are decoded, so a "decompression bomb" can't exhaust memory.
- One bad image never stops the run. A missing, private, oversized or broken image gets one error row that explains the problem, and that row is free.
Use cases
- Photo libraries and DAM: camera, lens, settings and date taken for every image, ready for a spreadsheet or database.
- Copyright and licensing checks: author, copyright and keywords embedded by photographers and agencies.
- Location audits: find which published images still carry GPS coordinates (
hasGps), then strip them with the Image Converter. - Duplicate and re-upload detection: group a scraped catalogue's product photos by pHash to find the same picture under different URLs.
- Colour tagging: dominant and average colours for product images, to filter or sort by colour.
- Image QA: dimensions, megapixels, aspect ratio, DPI, colour profile, transparency and animation for a whole dataset of images.
How to use it
- Add Image URLs (one per line), and/or pick a Dataset to enrich. For datasets, set Image URL fields if your field isn't one of
imageUrl,imageUrls,image,images,thumbnailUrl,thumbnail,photo,srcorurl. A field that holds a list of URLs gives one row per image. - Choose what to extract. GPS, colours and hashes are on by default. Raw EXIF and near-duplicate search are off.
- Run it. Export the rows as CSV, Excel or JSON, or chain the run with an integration. The run summary is saved as
OUTPUTin the key-value store.
Input example
{"imageUrls": ["https://raw.githubusercontent.com/ianare/exif-samples/master/jpg/Canon_40D.jpg","https://raw.githubusercontent.com/ianare/exif-samples/master/jpg/gps/DSCN0010.jpg"],"includeGps": true,"includeColors": true,"includeHashes": true,"findDuplicates": true,"duplicateThreshold": 6}
Output example (one row per image; the values are illustrative)
{"url": "https://example.com/photos/IMG_4127.jpg","finalUrl": "https://cdn.example.com/photos/IMG_4127.jpg","statusCode": 200,"format": "jpeg","mimeType": "image/jpeg","width": 4000,"height": 6000,"megapixels": 24.0,"aspectRatio": 0.6667,"orientation": 6,"mode": "RGB","hasAlpha": false,"animated": false,"frames": 1,"fileBytes": 8251334,"colorProfile": "sRGB IEC61966-2.1","dpi": 72,"hasExif": true,"camera": {"make": "Canon", "model": "Canon EOS R6", "lens": "RF24-105mm F4 L IS USM"},"settings": {"exposureTime": "1/250", "exposureSeconds": 0.004, "fNumber": 8.0, "iso": 200, "focalLength": 50.0,"focalLength35mm": null, "flash": "Off, did not fire", "flashFired": false, "whiteBalance": "Auto"},"dateTaken": "2024-05-01T14:03:22+02:00","dateTakenUtc": "2024-05-01T12:03:22Z","timezoneOffset": "+02:00","software": "Adobe Lightroom Classic 13.0","author": "Jane Photographer","copyright": "© 2024 Jane Photographer","title": "Harbour at dawn","description": "Fishing boats in the harbour","keywords": ["harbour", "boats", "dawn"],"hasGps": true,"gps": {"lat": 52.3700944, "lon": 4.8838889, "altitude": 58.5,"mapsUrl": "https://www.google.com/maps?q=52.3700944,4.8838889", "timestampUtc": "2024-05-01T12:03:21Z"},"dominantColors": [{"hex": "#2f5d8a", "percent": 31.4}, {"hex": "#d9c7a0", "percent": 22.0},{"hex": "#1c2a33", "percent": 18.7}, {"hex": "#8fa9bf", "percent": 15.2},{"hex": "#5e4a36", "percent": 6.1}],"averageColor": "#6b7a84","hashes": {"sha256": "9f2b…", "aHash": "ffc3810000183cff", "pHash": "b696446969490fbd", "dHash": "042c6c9c1f638801"},"duplicateOf": null,"duplicateDistance": null,"rawExif": null,"error": null,"analyzedAt": "2026-10-21T12:00:00Z"}
widthandheightare the size as displayed: the EXIF orientation is applied, so a portrait phone photo stored sideways (orientation 6 or 8) is reported as portrait.megapixelsis the stored pixel count.camera,settingsandgpsarenullwhen the file has none of those fields. Other fields arenullwhen the file doesn't contain them.hasGpssays whether the file contains a GPS position, even when GPS location is off.rawExif(with All EXIF tags) is an object of tag name → value. Rationals become numbers, and binary values become"<N bytes>".- A failed image has
errorset and the metadata fieldsnull. When you enrich a dataset with Keep the item's original fields on, the item's own fields come first in each row.
Near-duplicates
With Find near-duplicates on, each image's pHash is compared with every image analyzed before it (in this run, and in the earlier part of a resumed run):
- Per row:
duplicateOfis the URL of the first earlier image within the Near-duplicate threshold, andduplicateDistanceis how many of the 64 bits differ (0 = the same picture to the hash). The first image of a group hasduplicateOf: null. - Groups, in the run summary:
OUTPUT→duplicateGroupslists every group as{"group": 1, "count": 3, "images": [{"url": "…", "index": 0}, …]}, whereindexis the row's position in the dataset (0-based). Groups chain: if A matches B and B matches C, all three are in one group even if A and C are further apart. Up to 20,000 images are listed (duplicateGroupsTruncatedsays when more were found). - Threshold: 0 matches visually identical images. 6 (the default) also catches resized, re-compressed and slightly edited copies. Values above about 10 start to match different photos of similar scenes. Flat, single-colour images all hash alike and group together.
Rows can't be changed after they are stored, so the group number isn't a column. Use duplicateOf in the rows, or duplicateGroups in OUTPUT.
How much does it cost?
Pay per event, Apify platform usage included:
- $0.005 per analyzed image (
image-analyzed): each image that was downloaded and decoded, and got its metadata row. - $0.005 run start per GB of Actor memory (minimum one; at the default 1 GB that's $0.005 a run). The run start applies to every run, even one where every image fails.
Apify Store discounts: the price above is for Apify's Free plan. Paid plans pay less per analyzed image: $0.0045 on Starter, $0.004 on Scale, $0.0035 on Business. The "from" price at the top of the Store page is the Business price.
Free: images that fail (download errors, HTTP errors such as 404 or 403, blocked private addresses, invalid URLs, files over 50 MB, pages or files that aren't images, images over the size limit, damaged files) and repeats skipped by Analyze each URL once. Near-duplicate search, raw EXIF, colours and hashes cost nothing extra.
Worked examples:
Examples use the Free-plan rate.
- 1,000 product photos at the default 1 GB: 1,000 × $0.005 + $0.005 run start = $5.005.
- 200 image links where 20 return 404: 180 × $0.005 + $0.005 = $0.905. The 20 failed rows are free.
- A daily run on 50 new images: 50 × $0.005 + $0.005 = $0.255 per run, about $7.65 per month (30 runs).
- 2,000 large camera photos with the memory raised to 4 GB: 2,000 × $0.005 + 4 × $0.005 = $10.02.
If you set a maximum cost per run, the Actor stops cleanly at that limit: images beyond it are neither stored nor charged.
Privacy and lawful use
GPS coordinates, dates, camera details and author names in image metadata can be personal data, for example under the GDPR in the EU and UK, and under similar laws elsewhere. A photo's location can reveal where someone lives or was at a given time. You are responsible for having a lawful basis to collect and use this data, and for using it in line with the law and the image owners' rights. Turn off GPS location if you don't need it. Camera and lens serial numbers and the camera owner's name are never output. To publish images without their metadata, strip it with the Image Converter.
FAQ and limits
Why are camera, date and GPS empty for my image?
The metadata isn't in the file you linked. Social networks (Instagram, Facebook, X, WhatsApp), most image CDNs, and many CMSs remove EXIF and GPS when they resize or re-encode an image. Phones also often leave out the location when you share a photo. Link the original file where you can. The Actor's request doesn't list WebP or AVIF among the formats it accepts, so CDNs that pick a format from the request are less likely to send a re-encoded copy.
Which formats are supported?
JPEG, PNG (and APNG), WebP, GIF, AVIF, TIFF and BMP. HEIC / HEIF (iPhone photos) isn't supported: the decoder needed for it isn't included, for licensing reasons. Convert HEIC to JPEG first (iPhones can share as JPEG, Most Compatible). RAW camera files, SVG and PDF aren't supported either. For animations and multi-frame files, frames counts the frames and the colours and hashes come from the first frame.
What isn't read?
Vendor MakerNotes (shutter count, some lens names that only appear there), and XMP fields beyond the common descriptive ones listed above. All EXIF tags shows every standard EXIF tag except serial numbers, the owner name and the MakerNote.
How do the hashes compare with other tools?
aHash, pHash and dHash use the same definitions as the popular Python imagehash library (8×8 grid, 64 bits, hex with the first pixel as the most significant bit). They are computed from a reduced copy of the image with the EXIF orientation applied, so values can differ from other tools by a bit or two. Compare hashes with a Hamming distance, not with equality. sha256 is of the downloaded file's bytes.
Is 0,0 a location?
Many devices write 0,0 when they have no GPS fix, so 0,0 (and missing or 0/0 values) is treated as "no position".
Limits
- Download size: 50 MB per image. The file is downloaded in full (the pixels are decoded to check the image and compute colours and hashes).
- Image size: JPEG up to 150 megapixels (decoded at reduced scale); other formats up to 60 megapixels. Larger images get a free error row.
- No proxy, cookies or browser: images behind sign-ins, bot protection or hotlink protection can fail with HTTP 403.
- Google Drive and Dropbox share links to a single file are turned into download links. Folder links aren't supported.
- If the platform restarts a run, already stored rows are skipped and the run continues after them. Near-duplicate search reloads the earlier rows' hashes.
Related Actors
| Actor | Use it to |
|---|---|
| Image Converter & Resizer | Strip EXIF and GPS before publishing, or convert and resize the images you analyzed. |
| Dataset Filter & Transform | Keep only the rows you need (for example hasGps: true), or flatten camera and settings into columns. |
| Merge & Deduplicate Datasets | Keep only new image links between runs before analyzing them, or deduplicate rows by hashes.sha256. |
| Google Sheets Import & Export | Put the metadata rows into a Google Sheet. |
Image decoding: Pillow. Hash definitions: imagehash (not a dependency; implemented here).