Confirm GPS metadata was removed from an image
Compare a photo's metadata before and after stripping and confirm that no location survives: in the example, the latitude, longitude and altitude tags are listed as the 3 removed, and any GPS tag left behind makes the check fail. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Runs in your browser. Free, unlimited — your data never leaves this page.
Removing location metadata is easy to claim and important to verify. This capability compares parsed image metadata captured before and after a strip operation, identifies GPS-related fields recursively, and confirms that none survive in the result. It reports the exact metadata paths removed, making the result useful for automated privacy checks, publishing workflows, and audit records. The comparison is deterministic, runs without network access, and accepts common nested EXIF and XMP metadata structures.
Capture comparable metadata before and after stripping
Start by extracting metadata from the original image and from the stripped output with the same metadata reader whenever possible. Using one reader keeps namespace names and nesting consistent, which makes the removed-tag report easier to interpret. The checker walks both objects recursively, so a camera field such as <code>EXIF.GPSLatitude</code>, an XMP key such as <code>XMP.exif:GPSLongitude</code>, and values inside a nested <code>GPS</code> object can all be recognized.
The input is metadata, not image bytes: this capability verifies the evidence produced by your extraction and stripping workflow rather than editing the file itself. Preserve the original metadata snapshot before running the stripper, because it establishes which location tags existed and lets the result name what disappeared. Other camera, copyright, orientation, and descriptive fields may remain without causing an error.
For reliable audits, keep the two snapshots with the strip job identifier and ensure they refer to the exact source and output files being evaluated.
Understand confirmation and removed-tag reporting
A successful response means the after snapshot contains no recognized GPS leaf tags. A before snapshot with no GPS tags is still a valid comparison: it confirms that the after snapshot is also clear and returns an empty removed list. Recognition is based on metadata key names and GPS namespaces rather than coordinate values, so a present GPS tag still counts when its value is zero, blank, or null.
That conservative rule matters because privacy verification should test whether the field remains, not guess whether its value is usable. Empty GPS container objects do not count as tags because they carry no leaf metadata. Paths are stable and sorted, allowing callers to store results, compare runs, or assert an exact removal policy without depending on object insertion order.
Fail the workflow when location metadata survives
Treat that result as a failed strip operation: do not publish, upload, email, or archive the image as privacy-safe. Instead, inspect whether the stripping tool omitted an EXIF GPS field, preserved an XMP location property, or rewrote metadata under a different namespace. Run the strip step again with the appropriate policy, extract fresh metadata from the new output, and repeat the confirmation.
This fail-closed behavior prevents a partial cleanup from looking successful merely because some coordinates disappeared. The traversal is bounded by depth and node limits so malformed or unexpectedly huge metadata cannot consume unbounded resources. It is also deterministic and uses no network, current time, or random values, making the same pair of snapshots produce the same answer.
Use the response as one control in a larger privacy pipeline; also ensure that filenames, visible pixels, captions, sidecar files, and platform-specific asset databases do not independently disclose a location.
What you can do with it
Block unsafe photo publishing
Stop a CMS or social publishing job when the processed image still exposes any GPS metadata field.
Audit a media privacy pipeline
Record exactly which GPS paths disappeared between the source metadata and the sanitized output metadata.
FAQ
Does this capability remove GPS metadata from an image?
No. It verifies parsed metadata from before and after a separate strip operation and reports the GPS tags that disappeared.
Are nested EXIF and XMP structures supported?
Yes. The checker recursively scans nested objects and recognizes GPS-prefixed fields and values inside GPS namespaces.
Does a null or blank GPS value count as remaining metadata?
Yes. Privacy confirmation checks whether the GPS tag exists, regardless of whether its current value appears useful.
What happens if a GPS tag survives the strip?
The check fails instead of reporting success, and it names the paths that remain. Treat the image as not privacy-safe: run the strip step again, extract fresh metadata from the new file and repeat the check.
Does a GPS tag with an empty or zero value still count?
Yes. Recognition is based on the tag name, not its value, so a GPS entry that is blank, zero or empty still counts as remaining. An empty GPS group with nothing inside it does not.
Can I check an image that never had location data?
Yes. If the before snapshot has no GPS tags, the comparison is still valid: it confirms that the after snapshot is clear too and returns an empty list of removed tags.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/image/metadata-gps-strip-confirm \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"before_metadata":{"EXIF":{"Make":"Example Camera","GPSLatitude":"51 deg 30'\'' 26.00 N","GPSLongitude":"0 deg 7'\'' 39.00 W"},"XMP":{"Creator":"Studio"}},"after_metadata":{"EXIF":{"Make":"Example Camera"},"XMP":{"Creator":"Studio"}}}'const res = await fetch("https://api.kit.forhosting.com/image/metadata-gps-strip-confirm", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"before_metadata": {
"EXIF": {
"Make": "Example Camera",
"GPSLatitude": "51 deg 30' 26.00 N",
"GPSLongitude": "0 deg 7' 39.00 W"
},
"XMP": {
"Creator": "Studio"
}
},
"after_metadata": {
"EXIF": {
"Make": "Example Camera"
},
"XMP": {
"Creator": "Studio"
}
}
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/image/metadata-gps-strip-confirm",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"before_metadata": {
"EXIF": {
"Make": "Example Camera",
"GPSLatitude": "51 deg 30' 26.00 N",
"GPSLongitude": "0 deg 7' 39.00 W"
},
"XMP": {
"Creator": "Studio"
}
},
"after_metadata": {
"EXIF": {
"Make": "Example Camera"
},
"XMP": {
"Creator": "Studio"
}
}
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/image/metadata-gps-strip-confirm", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"before_metadata":{"EXIF":{"Make":"Example Camera","GPSLatitude":"51 deg 30\' 26.00 N","GPSLongitude":"0 deg 7\' 39.00 W"},"XMP":{"Creator":"Studio"}},"after_metadata":{"EXIF":{"Make":"Example Camera"},"XMP":{"Creator":"Studio"}}}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"before_metadata":{"EXIF":{"Make":"Example Camera","GPSLatitude":"51 deg 30' 26.00 N","GPSLongitude":"0 deg 7' 39.00 W"},"XMP":{"Creator":"Studio"}},"after_metadata":{"EXIF":{"Make":"Example Camera"},"XMP":{"Creator":"Studio"}}}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/image/metadata-gps-strip-confirm", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"before_metadata": {
"EXIF": {
"Make": "Example Camera",
"GPSLatitude": "51 deg 30' 26.00 N",
"GPSLongitude": "0 deg 7' 39.00 W"
},
"XMP": {
"Creator": "Studio"
}
},
"after_metadata": {
"EXIF": {
"Make": "Example Camera"
},
"XMP": {
"Creator": "Studio"
}
}
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "image.metadata_gps_strip_confirm",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_mb | 15 |
max_megapixels | 12 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
If even one GPS tag remains after stripping, the request returns an input error instead of a misleading success result.
Capture comparable metadata before and after stripping
Submit those parsed objects as <code>before_metadata</code> and <code>after_metadata</code>.
Understand confirmation and removed-tag reporting
The <code>confirmed</code> field is true, <code>gps_tags_after</code> is zero, and <code>removed_tags</code> lists the sorted paths that were present before stripping. <code>removed_count</code> gives the list length, while <code>gps_tags_before</code> makes the initial exposure explicit.
Fail the workflow when location metadata survives
If the after snapshot includes any GPS tag, the capability returns <code>invalid_input</code> and names the surviving paths in the message.
Integration use cases
Test metadata stripping tools
Use fixed before-and-after fixtures to catch regressions when an image library, encoder, or stripping policy changes.
Technical questions
What happens if a GPS tag remains?
The request fails with an invalid_input error that lists the surviving metadata paths, so a caller cannot mistake partial stripping for success.
How much does an API check cost?
Each request costs $0.002. The deterministic browser implementation uses the same core checking logic.