Image Metadata Remover — Strip EXIF, GPS & Serials, Lossless avatar

Image Metadata Remover — Strip EXIF, GPS & Serials, Lossless

Pricing

from $0.80 / 1,000 image processeds

Go to Apify Store
Image Metadata Remover — Strip EXIF, GPS & Serials, Lossless

Image Metadata Remover — Strip EXIF, GPS & Serials, Lossless

Remove EXIF, GPS location, camera serials, names and edit history from JPEG, PNG, WebP, HEIC, AVIF and TIFF, and thumbnails from JPEG, PNG and WebP, without re-encoding: pixels stay identical, checked on every file. Content Credentials and AI labels are kept. $0.001 per image.

Pricing

from $0.80 / 1,000 image processeds

Rating

0.0

(0)

Developer

Logan Parker

Logan Parker

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

8 hours ago

Last modified

Share

Remove the metadata that gives a photo away — GPS location, camera and phone serial numbers, names and contact details, captions and editing history — from JPEG, PNG, WebP, HEIC, AVIF and TIFF images, and embedded thumbnails from JPEG, PNG and WebP, without re-encoding them: the pixels stay identical, and every file is checked before it is returned. It is for anyone publishing, sending or selling photos, and for AI agents, which can call and pay for it through Apify's MCP server and agentic payments; Content Credentials (C2PA) and AI-generation labels are always kept, never stripped. It costs $0.001 per image, and an image that fails is never charged.

Example result

Example record for the minimal input under How to use it, as this Actor's code returned it in a local run on 2026-10-27 (the cleaned 835-byte JPEG is in the run's key-value store; outputUrl is shown in its platform form, the store id written as STORE_ID). The record names the fields it found — never their values:

{
"url": "https://raw.githubusercontent.com/python-pillow/Pillow/262e8e48229197ef08792de41a6bdd94e42219a0/Tests/images/exif_gps.jpg",
"ok": true,
"format": "jpeg",
"width": 8,
"height": 8,
"reportOnly": false,
"removedGroups": [
"location",
"device",
"thumbnails",
"otherMetadata"
],
"keptGroups": [
"timestamps",
"structure"
],
"fieldsRemoved": 17,
"fieldsKept": 1,
"found": {
"location": [
"GPS:GPSAltitudeRef",
"GPS:GPSDateStamp",
"GPS:GPSDifferential",
"GPS:GPSLatitude",
"GPS:GPSVersionID"
],
"device": [
"ExifIFD:LensInfo",
"ExifIFD:LensMake",
"IFD0:Make",
"IFD0:Model",
"IFD0:Software"
],
"timestamps": [
"ExifIFD:DateTimeOriginal"
],
"thumbnails": [
"IFD0:OtherImageLength"
],
"otherMetadata": [
"ExifIFD:ExposureCompensation",
"ExifIFD:ExposureTime",
"ExifIFD:ISOSpeed",
"ExifIFD:Opto-ElectricConvFactor",
"ExifIFD:Sharpness",
"IFD0:BlackLevelDeltaH"
]
},
"aiLabel": false,
"digitalSourceTypes": [],
"contentCredentials": null,
"bytesBefore": 1097,
"bytesAfter": 835,
"pixelsIdentical": true,
"notes": [],
"key": "cleaned-000-81d9594089.jpg",
"outputUrl": "https://api.apify.com/v2/key-value-stores/STORE_ID/records/cleaned-000-81d9594089.jpg",
"sha256": "1c0ad852a7d2944f3decdbfe8b9bad08f9c6263296926740c98ce42bdb1bb90b"
}

How to use it

Start a run in Apify Console, by API or from an agent with an input like this one — it is the input Apify runs every day to test this Actor:

{"urls": ["https://raw.githubusercontent.com/python-pillow/Pillow/262e8e48229197ef08792de41a6bdd94e42219a0/Tests/images/exif_gps.jpg"]}
FieldTypeRequiredDefaultMeaning
urlsarray of stringsyes—Image URLs (JPEG, PNG, WebP, HEIC/HEIF, AVIF, TIFF), http or https, 1–100 per run, up to 100 MB each. Each URL becomes one record and, unless reportOnly is set, one cleaned file.
removeLocationbooleannotrueGPS position, altitude and direction, and place names (city, state, country, sub-location) in EXIF, XMP and IPTC.
removeDevicebooleannotrueCamera and phone make, model and serial numbers, lens details and serial, owner name, unique image ID, the maker's private notes (MakerNotes), and the software and computer that wrote the file.
removePeoplebooleannotrueArtist, creator, author and by-line names, the creator's address, phone, email and website, people shown, and the AI prompt writer's name.
removeTimestampsbooleannofalseWhen the photo was taken, digitized and modified, with time-zone offsets and sub-seconds, in EXIF, XMP, IPTC and PNG. Kept unless set.
removeThumbnailsbooleannotrueEmbedded thumbnails and preview images in JPEG, PNG and WebP (EXIF, Photoshop, XMP, MPF previews) and anything appended after a JPEG's end (a motion-photo video, an appended image). A thumbnail can show the photo before it was cropped or edited. A HEIF or AVIF thumbnail item and a TIFF's reduced-resolution image are kept.
removeDescriptionsbooleannotrueTitles, captions, descriptions, keywords, comments (EXIF, XMP, IPTC, JPEG and PNG comments) and ratings.
removeEditingHistorybooleannotrueXMP document and instance IDs, the editing history (which software did what, sometimes with file paths), Lightroom and Camera Raw settings, and Photoshop layers.
removeRightsbooleannofalseCopyright notices, rights, usage terms, licence and credit lines. Kept unless set: they are rights-management information.
removeColorProfilebooleannofalseThe embedded ICC colour profile. Kept unless set: removing it can change how colours look.
removeOtherMetadatabooleannotrueEverything else not listed: exposure, flash, focus and scene settings, lens corrections, unknown tags, Photoshop print settings.
reportOnlybooleannofalseList what each image carries, group by group, without changing or storing it. Charged like a cleaned image.

Every limit above is enforced by the input schema and again in code. The groups, in more detail:

  • Always kept, with no switch: provenance — Content Credentials (the C2PA manifest store: JPEG APP11, PNG caBX, WebP C2PA, the HEIF/AVIF box), the IPTC digital source type and AI-system fields in XMP, the remote-manifest link, and the text an image generator writes into a PNG (AUTOMATIC1111 and Forge parameters, ComfyUI prompt and workflow, InvokeAI, Fooocus, NovelAI); and structure — orientation, resolution, colour space, the coded image's own parameters, an MPF stereo pair and an HDR gain map.
  • A field ExifTool reads but that no group above names (exposure, flash, scene, unknown tags, a Print Image Matching block) is otherMetadata, and so is an APPn segment of a JPEG outside the standard set (JFIF, EXIF, XMP, ICC, MPF, Content Credentials, Photoshop/IPTC, Adobe): a maker's private block that the Actor cuts out itself. Face and person regions (Lightroom, digiKam, Picasa, Microsoft Photo, IPTC image regions) are people; drone flight altitudes and attitude are location; ImageMagick's exif: PNG keywords follow the EXIF field they copy. Every field lands in exactly one group.

Events and prices

Pay per event; platform usage is included in the price, never passed through.

EventTitleCharged whenFREE / BRONZESILVERGOLD / PLATINUM / DIAMOND
image-processedImage processedOne image cleaned and stored, or with reportOnly read and reported.$0.001$0.0009$0.0008

One event per image, charged only after the cleaned file is stored (or the report written) and its record written; whatever the format, size and number of fields removed. Apify also charges its standard apify-actor-start event: $0.00005 per GB of run memory (1 event, $0.00005, at the default 1,024 MB). The minimum maximum-charge a caller can set is $0.01.

Worked example on the FREE tier: the photo above costs $0.001 plus $0.00005 for the start, $0.00105 in all; a run of 100 photos costs 100 × $0.001 = $0.10 plus the start. Nothing is charged for an image that fails.

Call it from an agent

Through Apify's MCP server (https://mcp.apify.com), tool call-actor:

{"actor": "hermeskd/image-metadata-remover", "input": {"urls": ["https://raw.githubusercontent.com/python-pillow/Pillow/262e8e48229197ef08792de41a6bdd94e42219a0/Tests/images/exif_gps.jpg"]}, "callOptions": {"maxTotalChargeUsd": 0.01, "timeout": 1800}, "waitSecs": 30}

The call returns the run's status and its defaultDatasetId. Read the records with get-dataset-items:

{"datasetId": "<defaultDatasetId from the call>", "limit": 100}

Each record's outputUrl is the cleaned image itself (also readable with get-key-value-store-record and the record's key). As a dedicated tool, add https://mcp.apify.com?tools=hermeskd/image-metadata-remover to your MCP client. A photo finishes in about a second of work, so one call returns the result inside the 30-second wait; maxTotalChargeUsd caps what the run can charge, and when it is reached the remaining URLs come back as charge_limit_reached records and are not charged. To see what a photo reveals without changing it, add "reportOnly": true.

Output fields

One record per input URL, and one cleaned image per successful record in the run's default key-value store (none with reportOnly).

FieldMeaning
urlThe input URL; null only on the one invalid_input record of a run given no input.
oktrue when the image was cleaned and stored (or, with reportOnly, read); false with error.
formatThe image format read from the file's bytes; the cleaned file keeps it.
widthWidth in pixels as stored (before EXIF orientation is applied).
heightHeight in pixels as stored.
reportOnlytrue when the run only listed the metadata; nothing was changed or stored.
removedGroupsThe field groups found in the image and removed from it.
keptGroupsThe field groups found in the image and kept: the ones switched off, plus provenance (Content Credentials and AI labels, always kept) and structure (orientation, resolution, colour space).
fieldsRemovedHow many metadata fields were removed.
fieldsKeptHow many metadata fields were kept, structure fields not counted.
foundEvery metadata field found, by group: field names as directory:name (GPS:GPSLatitude, IFD0:Make, XMP-dc:Creator). Names only — values are never returned. structure is not listed.
aiLabeltrue when the image carries a label saying it was generated by AI (an IPTC digital source type such as trainedAlgorithmicMedia, or an image generator's PNG text). Always kept.
digitalSourceTypesIPTC digital source type codes found in the Content Credentials or XMP, such as trainedAlgorithmicMedia or digitalCapture.
contentCredentialsnull when the image has none; otherwise {present, kept (always true), stateBefore and stateAfter (Trusted, Valid or Invalid), verifiesAfterEdit, generator, digitalSourceTypes, carriesPersonalData, personalAssertions}. Removing any metadata makes a credential fail verification: it stays in the file, showing the file was edited after signing. carriesPersonalData is true when the kept credential holds an assertion that can name a person or place (an author or creator, an identity, embedded EXIF or IPTC); personalAssertions lists those assertions' labels, never their values. The Actor never removes them.
bytesBeforeSize of the downloaded image.
bytesAfterSize of the cleaned image.
pixelsIdenticaltrue: the coded image data (JPEG, PNG, WebP) or the decoded pixels (TIFF, HEIF, AVIF) were checked equal after the rewrite. A file that fails the check is never returned.
notesAnything kept that a caller may not expect (bytes after the end of a JPEG, a HEIF thumbnail image).
keyKey of the cleaned image in the run's default key-value store.
outputUrlThe cleaned image's key-value store record URL (API).
sha256SHA-256 of the cleaned file.
error{code, message} when ok is false.

Limits and run time

  • 1–100 URLs per run; files up to 100 MB each. The format is read from the file's bytes, never from its name or the server's content type; GIF, BMP, SVG, raw camera files and PDF are refused as not_image.
  • Nothing is re-encoded: ExifTool rewrites only the metadata. Before a file is returned, the Actor checks that every field of every removed group is gone, that every kept field is still there, that the coded image (JPEG, PNG, WebP) is byte-for-byte unchanged or the decoded pixels of every frame (TIFF, HEIF, AVIF) are equal, and that Content Credentials are carried byte-for-byte. A file that fails any check is never returned. TIFF, HEIF and AVIF images over 100 megapixels across their frames are refused as too_large, because their check decodes them. A TIFF, HEIF or AVIF image the decoder cannot read is not_image, found before anything is written. Every image build of this Actor runs the same checks on planted images of all six formats and on Content Credentials fixtures where its ExifTool is installed, and a build where any check fails is never deployed; each run logs the ExifTool version.
  • Content Credentials: a credential signs every byte of the file outside itself, so removing any metadata from a signed image makes the credential fail verification. It stays in the file, showing the file was edited after signing, and the record says so (contentCredentials.verifiesAfterEdit: false). With every switch off nothing is removed, and the file comes back byte for byte with its credential still verifying. Where a rewrite would drop the credential (a TIFF that carries one, with the ExifTool release this Actor was tested on), the image is refused as metadata_not_removable rather than returned without it. A kept credential can name its author or carry other personal assertions (a CreativeWork author, an identity, embedded EXIF or IPTC); the Actor does not remove it, and the record says so in contentCredentials.carriesPersonalData, naming the assertions by label. A damaged credential that reads differently once the file around it changes is refused as metadata_not_removable, so it is never altered.
  • A metadata block the Actor finds in the file but ExifTool cannot read (a PNG whose EXIF chunk follows a Content Credentials chunk) is refused as metadata_not_removable, never passed over as empty.
  • Thumbnails and previews are removed from JPEG, PNG and WebP. A HEIF or AVIF thumbnail is its own image item, not metadata, and a TIFF's second and later images are its pages or reduced-resolution copies: both are kept, and the record's notes say so. Bytes after the end of a JPEG (a motion-photo video, an appended image or preview) go with removeThumbnails; kept, they are noted. An MPF stereo pair and an HDR gain map are part of the picture and always kept. A Print Image Matching block inside a camera maker's notes is kept with them when removeDevice is off.
  • Removing the colour profile can change how colours look; the copyright notice, the licence and the dates are kept unless you switch them off.
  • Downloads: files download at 2 MB/s or faster — each download has a budget of 30 s plus 1 s per 2 MB of its declared size (or of the 100 MB cap when the server declares none), and stops when no byte arrives for 30 s; at most 2 requests a second go to one host. GitHub release links are refused (github.com's robots.txt disallows them); give a raw.githubusercontent.com address or your own storage.
  • Typical run time, measured on 2026-10-27 on one CPU core: about 0.6 to 1 second of work per photo; the 15 benchmark images, from 1 KB to a 51-megapixel HEIC, took 12.9 seconds in all. The default 1,024 MB is enough for a 51-megapixel HEIC (569 MB at peak); the default run timeout is 1,800 seconds.

Errors

Errors are records with ok: false and error.code; none is charged and no file is stored.

error.codeMeaning
download_failedThe URL did not return the file (status, network error, a stall of 30 s, or slower than its download budget).
not_imageNot a JPEG, PNG, WebP, HEIC/HEIF, AVIF or TIFF image (read from its bytes), an empty body, or a damaged file the container walk, ExifTool or the decoder cannot read.
too_largeOver 100 MB, or a TIFF, HEIF or AVIF image over 100 megapixels across its frames.
metadata_not_removableA field could not be removed without rewriting the image, a metadata block could not be read, the metadata is too damaged to rewrite, removing it would also remove the Content Credentials or AI label, or a damaged credential reads differently after the edit; the message names the reason.
robots_disallowedrobots.txt forbids fetching the URL.
blocked_hostThe host is on the deny-list, or resolves to a private or local address.
timeoutThe image did not finish within the run's time budget.
internal_errorUnexpected failure, including a rewrite that failed the Actor's own checks; message carries the class.
charge_limit_reachedThe run's maximum total charge cannot pay for this image; it was not processed.
invalid_inputThe run input passed the input schema but cannot be used (for example a switch that is not true or false, or no URL at all); the message names the field. One record per input given, or one with url: null when none was given; nothing is processed.

The run fails only when every input failed with an Actor-side code (internal_error, timeout), so a broken Actor is visible. Every other run succeeds — including one where nothing was cleaned because of the caller's own inputs, or where those and Actor-side failures are mixed.

Sources and terms

The source is the caller's image. Process only images you have the right to process. The Actor removes metadata; it never removes Content Credentials, AI-generation labels, watermarks or signatures, and it is not a way to pass an AI image off as a photograph. Its records never contain a metadata value — not a position, serial number, name, address or caption, and not the author or signer named inside a credential — only field names, counts, the credential's verification state, its generator software, its IPTC digital source type and the labels of its personal assertions. A kept Content Credential can name its author, and the Actor does not remove it. The cleaned image is returned to the caller in the run's own key-value store. Fetching follows the Hermes fetch policy: robots.txt is obeyed for the user-agent HermesBot (and *), and a disallowed URL is refused without a request; platforms whose terms forbid automated access, and people-search sites, are on a deny-list and refused without a request; private and local addresses are refused, after DNS and on every redirect; the user-agent is HermesBot/1.0 (+https://apify.com/hermeskd); no login, cookies, credentials, CAPTCHA solving, evasion or proxies are used.

The tools are ExifTool by Phil Harvey (the Debian package, Perl Artistic Licence or GPL), c2pa-python from the Content Authenticity Initiative's C2PA project (Apache-2.0 or MIT) to read Content Credentials, and Pillow with pillow-heif (HPND; BSD-3-Clause, with libheif under LGPL) to decode images for the pixel check.

Not affiliated

This Actor is not affiliated with ExifTool or its author, with the C2PA, the Content Authenticity Initiative or Adobe, with the Pillow project, whose public test images the examples use, with the pillow-heif project, or with IPTC. ExifTool, c2pa-python, Pillow and pillow-heif are used under their open-source licences.

Changelog

  • 1.0 (2026-10-27) — before release, from the QA sweep: camera photos with a Print Image Matching block cleaned; an unreadable HEIF, AVIF or TIFF metadata block refused, never passed as empty; damaged or oversize TIFF, HEIF and AVIF files reported as not_image and too_large; a TIFF's pages kept; face regions, drone positions and ImageMagick's EXIF keywords in their groups; appended images and unknown APPn segments removed; carriesPersonalData on kept credentials; the image checks itself at build.
  • 1.0 (2026-10-27) — first release: lossless removal of location, device, people, timestamp, thumbnail, description, editing-history, rights, colour-profile and other metadata from JPEG, PNG, WebP, HEIC/HEIF, AVIF and TIFF, one switch per group; Content Credentials and AI labels always kept; a report-only mode; every file checked before it is returned.