Exiftool
exiftool reads, writes, and strips the metadata buried in a file: camera model and GPS in a JPEG, author and software in a PDF, ID3 in an MP3, and hundreds of other tags across image, document, audio, and video formats. It turns a file you already have into context: who made it, with what, when, and sometimes where. Reach for it first on any CTF forensics or stego artifact, on a downloaded document during OSINT, or when you need to scrub metadata before publishing.
Mental model: exiftool [options] [-TAG operations] FILE - no flag reads, -TAG=value writes, -TAG= deletes.
New to file metadata? Core concepts
- Tag: one named field like
AuthororGPSLatitude; no flag reads it,-TAG=valuewrites,-TAG=deletes - Group: where a tag lives -
EXIF(cameras),IPTC/XMP(publishing),PDF,ID3(audio);-G1shows it, and the same field can appear in several groups at once - Short name vs description:
-sprints the exact tag name you must use to write; the default label is just a pretty description - Composite tag: a convenience value derived from others (
GPSPosition,ImageSize); read-only, so write the underlyingGPSLatitude/GPSLongitudeinstead - Unknown / duplicate tags: hidden by default;
-udecodes unknown ones and-akeeps duplicates, where CTF authors stash a flag - Embedded preview: a thumbnail stored inside the file, often the un-edited original after someone cropped or painted over the full image
FILE_original: the automatic backup exiftool saves on any write, unless-overwrite_originaldiscards it
When to reach for exiftool (and when not)
Reach for it to read the metadata on a CTF forensics or stego artifact, surface GPS/author/software during OSINT, scrub identifying fields before publishing, batch a folder into a catalog, or fix and shift wrong capture timestamps.
Reach for something else when the payload is hidden inside the pixels or appended past the file’s real end (steghide or binwalk carve it out), you only need a fast type guess (file) or the printable strings exiftool’s parsers skip (strings), or you want purpose-built multi-format sanitization (mat2) or a lighter EXIF/IPTC/XMP reader (exiv2).
Install, update, verify#
sudo apt install -y libimage-exiftool-perl # Debian / Ubuntu / Kali
sudo dnf install -y perl-Image-ExifTool # Fedora / RHEL
brew install exiftool # macOS
sudo apt install --only-upgrade -y libimage-exiftool-perl # update
exiftool -ver # version number
command -v exiftool # confirm it is on PATH
Prefer the package manager: it pulls the Perl dependency for you. On Windows, grab the standalone build; it ships as exiftool(-k).exe, so rename it to exiftool.exe on your PATH. New releases add tag and format definitions, so an up-to-date binary reads more obscure fields correctly.
Flags you’ll actually use#
Skim these first; the cheat sheet below is these flags combined.
| Flag | Does | Flag | Does |
|---|---|---|---|
| (none) | Read all tags | -TAG=val | Write a tag |
-G1 | Show group of each tag | -TAG= | Delete a tag |
-s | Short tag names | -all= | Strip all metadata |
-a -u | Duplicate + unknown tags | -overwrite_original | No _original backup |
-c "%.6f" / -n | GPS as decimal | -tagsFromFile | Copy tags from another file |
-b | Raw binary value of a tag | -r | Recurse into directories |
-if 'COND' | Filter files by a tag | -j / -csv | JSON / CSV output |
Cheat sheet#
The Read block builds up one flag at a time; stop at the line that answers your question.
# Read: start bare, add one flag at a time
exiftool FILE # 1. every tag (the right first move)
exiftool -G1 FILE # 2. + which group each tag lives in
exiftool -s FILE # 3. + exact short tag names (to write)
exiftool -a -u -G1 FILE # 4. + duplicate and unknown tags (CTF)
exiftool -Comment -Author -Software FILE # just the high-signal fields
# Location (GPS)
exiftool -c "%.6f" -GPSPosition FILE # coords as decimal degrees
exiftool -n -GPSPosition FILE # signed decimal, map-ready
exiftool -r -if '$GPSLatitude' -filename -gpsposition FILE_DIR # only geotagged files
# Hunt for hidden text
exiftool FILE | grep -iE 'comment|flag|note|description|copyright'
# Extract embedded data
exiftool -b -ThumbnailImage FILE > thumb.jpg # the EXIF thumbnail
exiftool -b -PreviewImage FILE > preview.jpg # larger embedded preview
exiftool -htmlDump FILE > dump.html # annotated hex map (trailing data)
# Documents
exiftool -Author -Creator -Producer -CreateDate -ModifyDate FILE.pdf
# Write / delete (keeps FILE_original unless -overwrite_original)
exiftool -Comment="lab note" FILE # set a tag
exiftool -GPS:all= FILE # drop only GPS tags
exiftool -all= -overwrite_original FILE # strip everything, no backup
exiftool -tagsFromFile SRC -all:all FILE # copy every tag from another file
# Timestamps
exiftool "-AllDates+=0:0:0 1:0:0" FILE # add one hour to all dates
exiftool '-FileName<CreateDate' -d '%Y%m%d_%H%M%S%%-c.%%e' FILE_DIR # rename by date
# Batch + machine-readable
exiftool -r FILE_DIR # recurse a whole tree
exiftool -j FILE | jq . # JSON for automation
exiftool -csv -Make -Model -CreateDate FILE_DIR/*.jpg # table of a folder
Command breakdowns#
Each block below explains one situation, the exact command, and what to expect back. TARGET_FILE is one authorized file, TARGET_DIR a folder of them.
Dump every tag in a file#
exiftool TARGET_FILE
A two-column report of tag names and values. Skim for Comment, Author, GPS, and date fields. This is the right first move on any unknown artifact.
See which group each tag lives in#
exiftool -G1 TARGET_FILE
Prefixes like [EXIF], [XMP], [IPTC], [PDF] so duplicate-looking fields make sense and you know the group to target on a write.
Surface hidden or unknown tags#
exiftool -a -u -G1 TARGET_FILE
-a keeps duplicate tags, -u extracts unknown or undecoded ones, exactly where CTF authors stash a flag the default view drops.
Grep the metadata for a flag#
exiftool TARGET_FILE | grep -iE 'comment|flag|note|description|copyright'
Comment, Description, UserComment, and Copyright are the usual hiding spots. Piping to grep beats scrolling a long report by hand.
Pull GPS coordinates as decimal for a map#
exiftool -c "%.6f" -GPSPosition TARGET_FILE # 40.446200 N, 79.982000 W
exiftool -n -GPSPosition TARGET_FILE # 40.446200 -79.982000
Empty output means no GPS was stored. The -n (signed) form pastes straight into a maps search.
Find every file in a folder that has GPS#
exiftool -r -if '$GPSLatitude' -filename -gpsposition TARGET_DIR
-if filters to files where the tag exists; you get a short list of only the geotagged ones instead of wading through the whole tree.
Extract the embedded thumbnail or preview#
exiftool -b -ThumbnailImage TARGET_FILE > thumb.jpg
exiftool -b -PreviewImage TARGET_FILE > preview.jpg
-b dumps the raw tag value. The thumbnail is often the un-edited original, a classic reveal when someone cropped or painted over the full image but left the EXIF preview behind. PreviewImage is the larger sibling some cameras embed.
Read a PDF’s author, creator, and dates#
exiftool -Author -Creator -Producer -CreateDate -ModifyDate TARGET_FILE.pdf
Producer and Creator name the software (and often its version); a create date that disagrees with the modify date is itself a lead.
Write or change a tag#
exiftool -Comment="checked $(date -I)" TARGET_FILE
Prints 1 image files updated and saves the original as TARGET_FILE_original. Confirm the exact tag name with -s first if you are unsure it will land.
Strip all metadata before publishing#
exiftool -all= -overwrite_original TARGET_FILE
Rewrites the file with metadata removed. Re-read it to verify nothing survived: this is the defensive move against your own files leaking author names, paths, and GPS.
Strip only GPS, keep the rest#
exiftool -GPS:all= TARGET_FILE
Removes location without touching camera or timestamp data. Useful when the capture context is fine to share but the coordinates are not.
Copy metadata from one file to another#
exiftool -tagsFromFile SOURCE_FILE -all:all TARGET_FILE
Clones every tag onto TARGET_FILE, useful for restoring metadata after a lossy re-encode stripped it.
Batch a folder into a spreadsheet#
exiftool -csv -Make -Model -CreateDate -GPSPosition -r TARGET_DIR > report.csv
One row per file; open in a spreadsheet or diff against a suspected source device.
Rename photos by their capture date#
exiftool '-FileName<CreateDate' -d '%Y%m%d_%H%M%S%%-c.%%e' TARGET_DIR
Renames using each file’s own CreateDate. %%e keeps the extension, %%-c appends a copy number to avoid collisions.
Shift wrong timestamps#
exiftool "-AllDates+=0:0:0 1:0:0" TARGET_FILE
Adds one hour to DateTimeOriginal, CreateDate, and ModifyDate at once. Shift format is Y:M:D h:m:s; use -= to subtract, for a camera stuck on the wrong timezone.
Dump the raw file structure#
exiftool -htmlDump TARGET_FILE > dump.html
An annotated hex map of the file, the fast way to spot trailing or appended data hiding after the image’s real end.
Reading the output#
| Field | Why it matters |
|---|---|
Comment / Description / UserComment | The most common CTF hiding spot, read first |
GPSPosition / GPSLatitude/Longitude | Strong OSINT lead, but trivially forged |
Author / Creator / Software | Who made it and with what tool (often a version) |
CreateDate vs ModifyDate vs file dates | Disagreement between them is itself a finding |
Same field across EXIF / XMP / IPTC | Normal duplication, use -G1 to tell them apart |
| Empty value for a tag | The tag is absent, not an error |
Troubleshooting#
| Problem | Cause | Fix |
|---|---|---|
command not found | Not installed / stale PATH | Reinstall; open a fresh shell |
Error: File not found | Wrong path or name | Check the path; quote names with spaces |
Warning: ... not supported | Format is read-only | Reading works; that format cannot be written |
| Tag write does nothing | Wrong tag name or group | Confirm with -s; prefix the group (-EXIF:...) |
| Edit corrupts the file | Unsupported write target | Restore the _original; work on a copy |
| No metadata at all | File already stripped | Expected for sanitized files; try carving tools |
| GPS reads back as DMS, not decimal | Default print conversion | Add -c "%.6f" or -n |
Gotchas#
- Editing writes in place. exiftool saves
FILE_originalby default, but-overwrite_originaldiscards it silently. Keep source files read-only and edit copies. -all=on a directory strips the whole tree. Test the write on one file before pointing it atTARGET_DIR.- A composite tag cannot be written.
GPSPosition,ImageSize, and friends are derived from other tags; set the underlyingGPSLatitude/GPSLongitudeinstead. - Stripping metadata drops the
Orientationtag too. A phone photo that relied on EXIF orientation can render sideways in viewers after-all=; re-check rotation before you ship. - The same text hides under different names.
Comment,UserComment, andXMP:Descriptionare separate tags, so clearing one can leave a copy behind; re-read (or grep) before you trust a scrub.
Pairs with#
file gives a fast type guess before exiftool digs in, and strings pulls the printable text exiftool’s parsers skip. When a comment or odd tag hints the data is inside the image, hand off to steghide or binwalk to carve it out, and jq filters the -j JSON into exactly the fields you want. For sanitization-only jobs across many formats, mat2 is purpose-built and exiv2 is a lighter EXIF/IPTC/XMP reader, but exiftool wins on format breadth and batch editing.