The cheat sheet covers OSINT metadata extraction from documents, images, and files for Red Team reconnaissance.
# Required system dependency (all methods)
sudo apt install libimage-exiftool-perl # Debian/Ubuntu/Kali
brew install exiftool # macOS
winget install OliverBetz.ExifTool # Windows
# pip (recommended)
pip install MetaDetective
metadetective -h
# Direct single-file download (no install, no deps)
curl -O https://raw.githubusercontent.com/aurelienguidi/MetaDetective/stable/src/MetaDetective/MetaDetective.py
python3 MetaDetective.py -h
# Docker
docker pull aurelienguidi/metadetective
docker run --rm -v $(pwd)/loot:/data aurelienguidi/metadetective -d /data
# Git clone
git clone https://github.com/franckferman/MetaDetective.git
cd MetaDetective
python3 src/MetaDetective/MetaDetective.py -h
# Analyze a directory (deduplicated singular view - default)
metadetective -d ./loot/
# Per-file display (all metadata per document)
metadetective -d ./loot/ --display all
# Formatted output (vertical list with markers)
metadetective -d ./loot/ --format formatted
# Summary stats + timeline
metadetective -d ./loot/ --summary --timeline
# Scrape + download from target site (depth 1 minimum for real use)
metadetective --scraping --url https://target.com/ \
--download-dir ~/loot/ --depth 2 --threads 8
# Scan preview (no download, just list files found)
metadetective --scraping --scan --url https://target.com/ --depth 1
# Export to HTML report
metadetective -d ./loot/ -e html -o ~/results/
# Analyze a single file
metadetective -f report.pdf
# Analyze a directory
metadetective -d ./loot/
# Filter to specific file types only
metadetective -d ./loot/ -t pdf docx xlsx
# Ignore/exclude matching values (regex supported)
metadetective -d ./loot/ -i "admin" "anonymous" "unknown"
# Extract only specific metadata fields
metadetective -d ./loot/ --parse-only "Author" "Creator Tool" "GPS Position"
# Per-file view (all metadata shown per file)
metadetective -d ./loot/ --display all
# Deduplicated cross-file view (default - best for username harvest)
metadetective -d ./loot/ --display singular
# Compact output format
metadetective -d ./loot/ --format concise
# Decorated output format
metadetective -d ./loot/ --format formatted
# Export as HTML (default)
metadetective -d ./loot/ -e
# Export as JSON
metadetective -d ./loot/ -e json
# Export as plain text
metadetective -d ./loot/ -e txt
# Custom output filename suffix
metadetective -d ./loot/ -e json -c pentest-corp
# Custom output directory
metadetective -d ./loot/ -e json -o ~/results/
# Full export: per-file JSON to custom dir
metadetective -d ./loot/ --display all -e json -o ~/results/
# Scan target site: list discovered files, no download
metadetective --scraping --scan --url https://target.com/
# Filter by file extensions during scan
metadetective --scraping --scan --url https://target.com/ \
--extensions pdf docx xlsx pptx
# Download discovered files
metadetective --scraping --url https://target.com/ \
--download-dir ~/loot/
# Deep crawl: depth 2, 8 threads, 5 req/sec rate limit
metadetective --scraping --url https://target.com/ \
--download-dir ~/loot/ --depth 2 --threads 8 --rate 5
# Follow links to external domains
metadetective --scraping --url https://target.com/ \
--download-dir ~/loot/ --follow-extern
| Flag | Argument | Description |
|---|---|---|
-f |
file [file ...] |
|
-d |
directory |
|
-t |
ext [ext ...] |
Filter to specific file types (e.g. pdf docx) |
-i |
pattern [...] |
Ignore/exclude values matching regex patterns |
--parse-only |
field [...] |
Extract named metadata fields only |
--display |
all / singular |
Per-file view vs. deduplicated cross-file view |
--format |
formatted / concise |
Output style: decorated or compact |
-e |
[html|txt|json] |
Export format (HTML default) |
-c |
suffix |
Custom filename suffix for export |
-o |
path |
Output directory for exported files |
--scraping |
-- | Enable web scraping mode |
--scan |
-- | |
--url |
https://... |
Target website URL |
--extensions |
ext [...] |
Limit scraping to these file types |
--download-dir |
path |
Save downloaded files here |
--depth |
int |
Crawl depth level |
--threads |
int |
Concurrent download threads |
--rate |
float |
Requests per second limit |
--follow-extern |
-- | Follow links to external domains |
--user-agent |
string\|preset |
Custom UA or preset (chrome-win, firefox-linux, googlebot, stealth...) |
--summary |
-- | Show statistical overview of extracted metadata |
--timeline |
-- | Display chronological document events |
--no-banner |
-- | Suppress ASCII banner (useful for scripting/piping) |
| Category | Formats | Key Metadata Fields |
|---|---|---|
| Documents | .pdf .docx .xlsx .pptx .odt .odp .rtf .xls |
|
| Structured | .csv .xml |
Embedded properties, generator info |
| Images | .jpg .jpeg .png .tiff .bmp .gif .svg .psd .heic .heif |
|
.eml .msg .pst .ost |
||
| Video | .mp4 .mov |
| Metadata Field | Found In | |
|---|---|---|
Author |
DOCX, PDF, XLSX | |
LastModifiedBy |
DOCX, XLSX | |
Company |
Office docs | Organization confirmation |
Creator Tool / Producer |
Software stack and version disclosure | |
Template |
DOCX | |
GPS Position |
JPEG, HEIC, MP4 | |
GPS Map Link |
MetaDetective output | Clickable Google Maps pin |
Camera Model + Serial |
JPEG | Device fingerprinting and correlation |
Software |
PNG, TIFF | Toolchain fingerprinting |
Hostname / Computer |
Office, PDF | |
Revision Number |
DOCX | Document history depth |
Hyperlinks |
PDF, DOCX | Internal URLs, intranet addresses |
From / To (email) |
EML, MSG | Confirmed phishing targets |
| Scenario | Command | Output |
|---|---|---|
| Got a domain, want to scan for files | metadetective --scraping --scan --url https://target.com/ |
List of exposed documents |
| Download all discovered files | metadetective --scraping --url https://target.com/ --download-dir ~/loot/ --depth 2 --threads 8 |
Files saved to ~/loot/ |
| Analyze local docs for usernames | metadetective -d ./loot/ --display singular -e json |
Deduplicated author/creator list |
| Extract only author fields from Office docs | metadetective -d ./loot/ -t docx xlsx pptx --parse-only "Author" "Last Modified By" "Company" |
Username + org names |
| Extract GPS from images | metadetective -d ./photos/ --parse-only "GPS Position" "GPS Map Link" |
Lat/lon + Google Maps links |
| Analyze email archives | metadetective -d ./mail/ -t eml msg --parse-only "From" "To" "X-Mailer" |
Confirmed email addresses + mail client |
| Software stack fingerprinting | metadetective -d ./loot/ -t pdf --parse-only "Producer" "Creator Tool" "Software" |
PDF generators, Office versions |
| Full stats + timeline | metadetective -d ./loot/ --summary --timeline |
Document creation/modification timeline |
| Stealth scraping (custom UA) | metadetective --scraping --url https://target.com/ --user-agent stealth --rate 2 |
Slow crawl with realistic user-agent |
# 1. Passive document discovery via site scan
metadetective --scraping --scan --url https://target.com/
# 2. Download all exposed docs
metadetective --scraping --url https://target.com/ \
--download-dir ~/loot/ --depth 2 --threads 8 --rate 3
# 3. Bulk metadata extraction (deduplicated)
metadetective -d ~/loot/ --display singular -e json
# 4. Parse usernames from JSON output
jq '.unique.Author[]' results.json | sort -u
# 5. Extract GPS from any images found
metadetective -d ~/loot/ --parse-only "GPS Position" "GPS Map Link"
# 6. Identify software stack from PDF Producer/Creator fields
metadetective -d ~/loot/ -t pdf --parse-only "Producer" "Creator Tool"
# 7. Map internal paths from Template and Hyperlinks
metadetective -d ~/loot/ --parse-only "Template" "Hyperlinks"
# 8. Cross-reference usernames against LinkedIn for confirmation
# 9. Use confirmed usernames for password spray / phishing pretexting
| Feature | ExifTool | metagoofil | ||
|---|---|---|---|---|
| Platform | Linux/Mac/Win | Linux/Mac/Win | ||
| All-in-one (crawl + extract + export) | No (extract only) | No (download only) | Partial | |
| Document discovery | No | Google/Bing dorks | Google/Bing/DDG | |
| Metadata extraction | Yes | No | Yes | |
| GPS extraction + map link | Raw coords only | No | No | |
| Email support (EML/PST/OST) | Partial | No | Limited | |
| Deduplication | singular) |
No | No | Yes |
| Summary + timeline | --summary --timeline) |
No | No | No |
| Export formats | JSON, CSV, XML | None | Internal DB | |
| Rate limiting + stealth UA | --rate + --user-agent) |
N/A | Delay only | No |
| RAW camera formats | Use with ExifTool | No | No | |
| Metadata removal | No | No | No | |
| Active maintenance | Yes | Yes | Last release 2021 |
MetaDetective is the only tool that combines web crawling, metadata extraction, deduplication, GPS mapping, and structured export in a single command. For RAW camera formats or metadata removal, pair MetaDetective with ExifTool for full coverage.
| Scenario | Best Tool |
|---|---|
| Full recon pipeline (crawl + extract + export) | --scraping + -e json |
| Deduplicated username list from loot | --display singular |
| GPS extraction + clickable map link | --parse-only "GPS Map Link" |
| Email archive (.pst/.ost/.eml) analysis | -t eml msg |
| Document timeline + statistics | --summary --timeline |
| Stealth scraping with rate control | --rate 2 --user-agent stealth |
| Google-dork for docs | metagoofil + MetaDetective |
| RAW camera formats | ExifTool |
| Strip metadata | mat2 |
| GUI recon (Windows) | FOCA (legacy) |
metagoofil finds documents via Google dorking. MetaDetective does not Google-dork - it crawls the target site directly. Use both for maximum coverage.
# 1. Install metagoofil
pip install metagoofil
# 2. Google-dork for docs (downloads to ./target_files/)
python metagoofil.py -d target.com -t pdf,doc,xls,pptx -n 50 -f
# 3. With delay + proxy to avoid Google 429 blocks
proxychains4 python metagoofil.py -d target.com -t pdf,docx -n 30 -e 3 -f
# 4. Feed metagoofil downloads into MetaDetective
metadetective -d ./target.com/ --display singular -e json --no-banner
# 5. Meanwhile, also crawl the target site directly
metadetective --scraping --url https://target.com/ \
--download-dir ./target_crawl/ --depth 2 --threads 8
# 6. Analyze crawled files too
metadetective -d ./target_crawl/ --display singular -e json --no-banner
# 7. Compare results - metagoofil may find docs not linked on the site
# MetaDetective crawl may find docs not indexed by Google
#!/bin/bash
# Metadata OSINT: scrape target site, extract, report
TARGET="${1:-target.com}"
LOOT="/tmp/meta_osint_${TARGET}"
RESULTS="${LOOT}/results"
mkdir -p "${LOOT}/downloads" "${RESULTS}"
echo "[*] Phase 1: Crawling and downloading files from ${TARGET}..."
metadetective --scraping --url "https://${TARGET}/" \
--extensions pdf docx xlsx pptx odt \
--download-dir "${LOOT}/downloads" \
--depth 3 --threads 8 --rate 3 --user-agent stealth --no-banner
echo "[*] Phase 2: Extracting metadata (deduplicated + JSON export)..."
metadetective -d "${LOOT}/downloads" \
--display singular -e json -o "${RESULTS}" -c "${TARGET}" --no-banner
echo "[*] Phase 3: Summary statistics + timeline..."
metadetective -d "${LOOT}/downloads" --summary --timeline --no-banner
echo "[*] Phase 4: Parsing intelligence from JSON..."
echo ""
echo "=== USERNAMES ==="
jq -r '.unique.Author[]? // empty' "${RESULTS}/"*"${TARGET}"*.json 2>/dev/null | sort -u
echo ""
echo "=== SOFTWARE VERSIONS ==="
jq -r '.unique["Creator Tool"][]? // empty' "${RESULTS}/"*"${TARGET}"*.json 2>/dev/null | sort -u
echo ""
echo "=== GPS HITS ==="
jq -r '.unique["GPS Position"][]? // empty' "${RESULTS}/"*"${TARGET}"*.json 2>/dev/null
echo ""
echo "=== COMPANIES ==="
jq -r '.unique.Company[]? // empty' "${RESULTS}/"*"${TARGET}"*.json 2>/dev/null | sort -u
echo ""
echo "[+] Done. Results in ${RESULTS}/"
echo "[+] Open HTML report: ${RESULTS}/"*".html"
After exporting with -e json, use jq to extract actionable intelligence.
# All unique authors -> potential AD usernames for spray
jq -r '.unique.Author[]' results.json | sort -u
# All unique "Last Modified By" -> recently active employees
jq -r '.unique["Last Modified By"][]' results.json | sort -u
# Combine author + last modified -> full username list
jq -r '(.unique.Author[]?, .unique["Last Modified By"][]?) // empty' results.json | sort -u > usernames.txt
# Software fingerprinting -> identify tech stack
jq -r '(.unique["Creator Tool"][]?, .unique.Producer[]?, .unique.Software[]?) // empty' results.json | sort -u
# GPS positions -> physical locations
jq -r '.unique["GPS Position"][]' results.json
# GPS map links -> clickable Google Maps URLs
jq -r '.unique["GPS Map Link"][]' results.json
# Company names -> confirm org and subsidiaries
jq -r '.unique.Company[]' results.json | sort -u
# Internal paths -> UNC shares, intranet URLs
jq -r '(.unique.Template[]?, .unique.Hyperlinks[]?) // empty' results.json | grep -i '\\\\|//\|intranet\|internal'
# Count per field -> identify richest metadata sources
jq -r '.unique | to_entries[] | "\(.value | length)\t\(.key)"' results.json | sort -rn
# Generate users.txt for password spray (first.last format)
jq -r '.unique.Author[]' results.json | sort -u | \
awk '{gsub(/ /,"."); print tolower($0)}' > spray_users.txt
# Exclude common default/garbage author values
metadetective -d ./loot/ \
-i "Administrator" "admin" "User" "unknown" "Anonymous" \
"Microsoft" "Adobe" "root" "Default" "test" "owner"
# Exclude specific software noise
metadetective -d ./loot/ \
-i "Microsoft Office" "Adobe Acrobat" "LibreOffice" "Google"
# Focus only on GPS-tagged files (images + videos)
metadetective -d ./loot/ -t jpg jpeg heic mp4 \
--parse-only "GPS Position" "GPS Map Link" "Camera Model Serial Number"
# Only author fields from Office docs
metadetective -d ./loot/ -t docx xlsx pptx \
--parse-only "Author" "Last Modified By" "Company"
# Only internal paths (template + hyperlinks)
metadetective -d ./loot/ -t docx pdf \
--parse-only "Template" "Hyperlinks"
# PDF-only software fingerprint
metadetective -d ./loot/ -t pdf \
--parse-only "Producer" "Creator Tool" \
--display singular -e json
# Full analysis excluding noise + JSON export
metadetective -d ./loot/ \
-i "admin" "unknown" "Microsoft" "Adobe" \
--display singular -e json -o ./results/ --no-banner
mat2 (Metadata Anonymisation Toolkit v2) is the simplest way to strip metadata before publishing documents. It handles all common formats automatically.
# Install
apt install mat2 # Debian/Ubuntu
pip install mat2 # pip
# Strip metadata from a file (creates .cleaned copy)
mat2 document.pdf
mat2 photo.jpg
# Preview what would be removed (dry run)
mat2 --show document.pdf
# Check if metadata is present
mat2 --check document.pdf
# Batch process all files in a directory
mat2 /path/to/publish/*.pdf
mat2 /path/to/publish/*.docx
mat2 /path/to/publish/*.jpg
# Verify with MetaDetective that metadata is gone
metadetective -f document.cleaned.pdf --no-banner
| Field | Risk | How MetaDetective finds it |
|---|---|---|
Author / LastModifiedBy |
--parse-only "Author" "Last Modified By" |
|
Company |
Organization leak | --parse-only "Company" |
Template path |
--parse-only "Template" |
|
GPS coordinates |
--parse-only "GPS Position" "GPS Map Link" |
|
Software / Producer |
Version disclosure | --parse-only "Producer" "Creator Tool" |
HostComputer |
Hostname leak | --parse-only "Host Computer" |
Revision history |
Edit trail | --parse-only "Revision Number" |
Hyperlinks |
Internal URL leak | --parse-only "Hyperlinks" |
Use MetaDetective to identify which files contain high-risk metadata, then mat2 to strip it before publishing.