API-Dokumentation

Extrahieren Sie Metadaten aus Dateien mit unserer einfachen und leistungsstarken API. Beginnen Sie mit Ihrem API-Schlüssel und analysieren Sie Dateien programmatisch.

Authentifizierung

Alle API-Anfragen erfordern einen API-Schlüssel. Sie können ihn auf zwei Arten bereitstellen:

1. Im Anforderungs-Header:

X-API-Key: YOUR_API_KEY_HERE

2. Als Abfrageparameter:

?key=YOUR_API_KEY_HERE

Metadaten Extrahieren

POST https://exiftools.com/api/v1/extract

Extract metadata from a file using a direct file upload, a URL, or a base64 data URL. Results are returned in the same response when processing finishes within a few seconds; otherwise the API answers 202 with a statusUrl to poll.

Anforderungsparameter

{
  "file": "binary_file_data", // Option 1: direct file upload
  "url": "https://example.com/image.jpg", // Option 2: URL. Can be passed as POST body or query string parameter
  "data_url": "data:image/jpeg;base64,/9j/4AAQ..." // Option 3: base64 data URL
  // Provide exactly one of the above
}

Beispielantwort

{
  "success": true,
  "status": "completed",
  "fileName": "image.jpg",
  "uuid": "123e4567-e89b-12d3-a456-426614174000",
  "processedAt": "2026-03-15T10:31:02+00:00",
  "author": "John Doe", // author, createDate, dimensions, cameraModel: only when the file has them
  "createDate": "2026-03-15 10:30:00",
  "fileSize": "4.2 MB",
  "fileSizeBytes": 4404019,
  "mimeType": "image/jpeg",
  "dimensions": "8192x5464",
  "cameraModel": "Canon EOS R5",
  "metadata": {
    "File": {
      "FileType": "JPEG",
      "MIMEType": "image/jpeg",
      "FileSize": "4.2 MB",
      "ImageWidth": 8192,
      "ImageHeight": 5464,
      "SHA256": "a5e50cbe66078249973d9a71230c4a8edbaedc26af11204042d3bce1f9ed4409"
    },
    "EXIF": {
      "Make": "Canon",
      "Model": "Canon EOS R5",
      "DateTimeOriginal": "2026:03:15 10:30:00",
      "ExposureTime": "1/1000",
      "FNumber": 2.8,
      "ISO": 100
    },
    "IPTC": {
      "By-line": "John Doe",
      "CopyrightNotice": "© 2026 John Doe"
    }
    // ... more groups: XMP, GPS, ICC_Profile, MakerNotes, Composite…
  }
}

Die Antwort hat dieselben Felder wie bei „Extraktionsergebnisse Abrufen“. PDF- und Office-Dateien erhalten außerdem einen embedded-Block, der direkt nach dem Hochladen meist noch "pending" ist: Rufen Sie das Ergebnis ein paar Sekunden später erneut ab, um die Dateien zu sehen (siehe Eingebettete Dateien).

Fehlerantworten

400Bad Request
{
  "success": false,
  "error": "Invalid request parameters"
}
401Unauthorized
{
  "success": false,
  "error": "Invalid API key"
}
500Internal Server Error
{
  "success": false,
  "error": "An error occurred while processing your request"
}

Extraktionsergebnisse Abrufen

GET https://exiftools.com/api/v1/extract/{uuid}

Retrieve the metadata extraction results for a specific UUID. Use this endpoint to check the status and get results after submitting a file or URL for processing. Requires your API key.

Anforderungsparameter

{
  "uuid": "required", // The UUID returned from the extract endpoint
  "X-API-Key": "required" // API key in header, or use ?key=YOUR_API_KEY
}

Beispielantwort (Abgeschlossen)

{
  "success": true,
  "status": "completed",
  "fileName": "image.jpg",
  "uuid": "123e4567-e89b-12d3-a456-426614174000",
  "processedAt": "2026-03-15T10:31:02+00:00",
  "author": "John Doe", // author, createDate, dimensions, cameraModel: only when the file has them
  "createDate": "2026-03-15 10:30:00",
  "fileSize": "4.2 MB",
  "fileSizeBytes": 4404019,
  "mimeType": "image/jpeg",
  "dimensions": "8192x5464",
  "cameraModel": "Canon EOS R5",
  "metadata": {
    "File": {
      "FileType": "JPEG",
      "MIMEType": "image/jpeg",
      "FileSize": "4.2 MB",
      "ImageWidth": 8192,
      "ImageHeight": 5464,
      "SHA256": "a5e50cbe66078249973d9a71230c4a8edbaedc26af11204042d3bce1f9ed4409"
    },
    "EXIF": {
      "Make": "Canon",
      "Model": "Canon EOS R5",
      "DateTimeOriginal": "2026:03:15 10:30:00",
      "ExposureTime": "1/1000",
      "FNumber": 2.8,
      "ISO": 100
    },
    "IPTC": {
      "By-line": "John Doe",
      "CopyrightNotice": "© 2026 John Doe"
    }
    // ... more groups: XMP, GPS, ICC_Profile, MakerNotes, Composite…
  },
  "embedded": { // PDF and Office files only, see Embedded Files
    "status": "done",
    "count": 1,
    "zip": "https://exiftools.com/api/v1/results/{uuid}/embedded.zip",
    "items": [
      {
        "position": 1,
        "kind": "image",
        "mime": "image/jpeg",
        // ...
        "url": "https://exiftools.com/api/v1/results/{uuid}/embedded/1"
      }
    ]
  },
  "contentCredentials": { // files with Content Credentials only, see Content Credentials
    "state": "trusted_legacy",
    "signer": "Adobe Inc.",
    // ...
    "aiGenerated": true
  }
}

Ergebnisse von PDF- und Office-Dateien enthalten außerdem einen embedded-Block: jede im Dokument gefundene Datei mit ihrem Download-Link und ein ZIP mit allen (siehe Eingebettete Dateien).

Dateien mit Content Credentials enthalten außerdem einen contentCredentials-Block: das Ergebnis der Prüfung ihrer C2PA-Signatur (siehe Content Credentials).

author, createDate, dimensions und cameraModel erscheinen nur, wenn die Datei sie enthält. metadata ist so gruppiert, wie ExifTool die Gruppen benennt (File, EXIF, IPTC, XMP, GPS, ICC_Profile, Composite…); welche Gruppen und Tags vorkommen, hängt von der Datei ab.

Fehlerantworten

401Unauthorized
{
  "success": false,
  "error": "Invalid API key"
}

Wird nur zurückgegeben, wenn ein ungültiger API-Schlüssel bereitgestellt wird

404Not Found
{
  "success": false,
  "error": "No extraction found with the given UUID."
}

Eingebettete Dateien

Bei einem PDF- oder Office-Dokument (docx, xlsx, pptx, OpenDocument) listet das Ergebnis im embedded-Block die darin gefundenen Bilder, Videos, Audiodateien und Anhänge auf, jeweils mit Download-Link, dazu ein ZIP mit allen Dateien. Die Links benötigen Ihren API-Schlüssel; ohne ihn sind sie null.

GET https://exiftools.com/api/v1/results/{uuid}/embedded/{position}
GET https://exiftools.com/api/v1/results/{uuid}/embedded.zip

Beispielantwort

"embedded": {
  "status": "done", // pending | done | partial | failed
  "count": 2,
  "zip": "https://exiftools.com/api/v1/results/{uuid}/embedded.zip",
  "items": [
    {
      "position": 1,
      "kind": "image", // image | video | audio | document | archive | other
      "mime": "image/jpeg",
      "ext": "jpg",
      "bytes": 64753,
      "width": 1023,
      "height": 158,
      "page": 1, // PDF page or slide number
      "name": null, // an attachment's own file name
      "risky": false,
      "url": "https://exiftools.com/api/v1/results/{uuid}/embedded/1"
    },
    {
      "position": 2,
      "kind": "document",
      "mime": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
      "ext": "xlsx",
      "bytes": 18311,
      "width": null,
      "height": null,
      "page": null,
      "name": "budget.xlsx",
      "risky": false,
      "url": "https://exiftools.com/api/v1/results/{uuid}/embedded/2"
    }
  ]
}

Die Dateien werden gesucht, sobald die Metadaten fertig sind. Solange status "pending" ist, rufen Sie das Ergebnis nach ein paar Sekunden erneut ab. "partial" bedeutet, dass ein Limit erreicht wurde und nur die ersten Dateien aufgeführt sind; "failed" bedeutet, dass das Dokument nicht gelesen werden konnte, zum Beispiel weil es ein Passwort braucht.

Hängen Sie ?view=1 an die url einer Datei an, um Bilder, Videos, Audio und PDFs im Browser zu öffnen, statt sie herunterzuladen. Als risky markierte Dateien (Programme, Skripte, Makros) werden immer heruntergeladen.

Fehlerantworten

403Forbidden
A file url or the ZIP requested without a valid API key.

Content Credentials

Dateien mit Content Credentials (C2PA) erhalten einen contentCredentials-Block. Wir prüfen sie während der Extraktion offline mit den offiziellen C2PA-Tools: ob die Signatur gültig ist, ob die Datei nach dem Signieren verändert wurde, ob die signierende Stelle auf einer Vertrauensliste steht und was die Credentials angeben (KI-Erzeugung, Aktionen, die Dateien, aus denen sie entstanden ist).

Beispielantwort

"contentCredentials": {
  "state": "trusted_legacy", // trusted | trusted_legacy | valid | invalid | remote | unchecked | error
  "signer": "Adobe Inc.",
  "certificateName": "cai-prod",
  "trustList": "itl", // c2pa (C2PA Trust List) | itl (earlier Content Credentials list)
  "signedAt": "2023-10-02T16:51:02+00:00",
  "timestamped": true,
  "algorithm": "Ps256",
  "generator": "Adobe Firefly 1.0",
  "title": "Generated image",
  "aiGenerated": true,
  "digitalSourceTypes": ["ai"],
  "actions": [
    { "action": "c2pa.created", "softwareAgent": "Adobe Firefly", "digitalSourceType": "ai" }
  ],
  "ingredients": [],
  "creator": [],
  "aiTraining": [],
  "checks": [
    { "code": "assertion.dataHash.match", "outcome": "success" },
    { "code": "signingCredential.trusted", "outcome": "success" },
    { "code": "signingCredential.ocsp.skipped", "outcome": "info" }
    // ...
  ],
  "manifestUrl": "https://exiftools.com/results/{uuid}/credentials?format=manifest",
  "checkedAt": "2026-10-15T16:36:48+00:00"
}

state: trusted bedeutet, dass die signierende Stelle auf der C2PA Trust List steht; trusted_legacy, auf der früheren Vertrauensliste von Content Credentials (2026 eingefroren, weiterhin gültig für das, was damit signiert wurde); valid, Signatur und Datei sind intakt, aber die signierende Stelle steht auf keiner vertrauenswürdigen Liste; invalid kommt mit einem Grund: changed (die Datei wurde nach dem Signieren bearbeitet), signature (die Signatur oder der Nachweis besteht die Prüfung nicht) oder expired; remote, die Datei verweist auf online gespeicherte Credentials, die wir nicht abrufen; unchecked, ein Ergebnis aus der Zeit vor der Prüfung. Eine vertrauenswürdige signierende Stelle sagt, wer die Datei erstellt hat, nicht, dass ihr Inhalt wahr ist.

checks listet jedes C2PA-Prüfergebnis mit seinem Statuscode und Ergebnis (success, info oder failure). manifestUrl liefert das vollständige C2PA-Manifest als JSON. Ein Widerruf wird nicht online geprüft.

Metadaten entfernen

POST https://exiftools.com/api/v1/remove

Entfernen Sie alle Metadaten aus einer Datei, einschließlich EXIF-Daten, GPS-Standort, IPTC, XMP und anderen sensiblen Informationen. Laden Sie eine Datei direkt hoch oder geben Sie eine URL zur Verarbeitung an. Erhalten Sie eine bereinigte Version ohne eingebettete Metadaten. Die bereinigte Datei steht über die zurückgegebene URL zum Download bereit.

Anforderungsparameter

{
  "file": "binary_file_data", // Option 1: direct file upload
  "url": "https://example.com/image.jpg", // Option 2: URL. Can be passed as POST body or query string parameter
  "data_url": "data:image/jpeg;base64,/9j/4AAQ..." // Option 3: base64 data URL
  // Provide exactly one of the above
}

Beispielantwort

{
  "success": true,
  "status": "completed",
  "uuid": "123e4567-e89b-12d3-a456-426614174000",
  "downloadUrl": "https://exiftools.com/download-cleaned/123e4567-e89b-12d3-a456-426614174000"
}

Die downloadUrl bietet einen direkten Link zum Herunterladen der bereinigten Datei mit allen entfernten Metadaten. Die Datei steht 24 Stunden lang zum Download zur Verfügung.

Cleaning runs on a queue. When it takes longer than the request waits, the response is 202 with "status": "processing" and a statusUrl (GET /api/v1/remove/{uuid}, same API key) that returns this same payload once the file is ready. A format no cleaner on the server handles comes back with "unchanged": true and a notice — its metadata is still inside.

Fehlerantworten

500Internal Server Error
{
  "success": false,
  "error": "An error occurred while processing your request"
}

Code-Beispiele

# File Upload - Using header
curl -X POST https://exiftools.com/api/v1/extract \
-H "X-API-Key: YOUR_API_KEY_HERE" \
-F "[email protected]"

# File Upload - Using query parameter
curl -X POST "https://exiftools.com/api/v1/extract?key=YOUR_API_KEY_HERE" \
-F "[email protected]"

# URL Processing - Using header
curl -X POST https://exiftools.com/api/v1/extract \
-H "X-API-Key: YOUR_API_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/image.jpg"}'

# URL Processing - Using query parameter
curl -X POST "https://exiftools.com/api/v1/extract?key=YOUR_API_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/image.jpg"}'

# Data URL (base64) - encode a local file inline - Using header
curl -X POST https://exiftools.com/api/v1/extract \
-H "X-API-Key: YOUR_API_KEY_HERE" \
-H "Content-Type: application/json" \
-d "{\"data_url\": \"data:image/jpeg;base64,$(base64 -i image.jpg)\"}"

# Data URL (base64) - encode a local file inline - Using query parameter
curl -X POST "https://exiftools.com/api/v1/extract?key=YOUR_API_KEY_HERE" \
-H "Content-Type: application/json" \
-d "{\"data_url\": \"data:image/jpeg;base64,$(base64 -i image.jpg)\"}"

# Get results by UUID - Using header
curl -X GET https://exiftools.com/api/v1/extract/123e4567-e89b-12d3-a456-426614174000 \
  -H "X-API-Key: YOUR_API_KEY_HERE"

# Get results by UUID - Using query parameter
curl -X GET "https://exiftools.com/api/v1/extract/123e4567-e89b-12d3-a456-426614174000?key=YOUR_API_KEY_HERE"

# Response (immediate results)
{
  "success": true,
  "status": "completed",
  "fileName": "image.jpg",
  "uuid": "123e4567-e89b-12d3-a456-426614174000",
  "processedAt": "2026-03-15T10:31:02+00:00",
  "author": "John Doe", # author, createDate, dimensions, cameraModel: only when the file has them
  "createDate": "2026-03-15 10:30:00",
  "fileSize": "4.2 MB",
  "fileSizeBytes": 4404019,
  "mimeType": "image/jpeg",
  "dimensions": "8192x5464",
  "cameraModel": "Canon EOS R5",
  "metadata": {
    "File": {
      "FileType": "JPEG",
      "MIMEType": "image/jpeg",
      "FileSize": "4.2 MB",
      "ImageWidth": 8192,
      "ImageHeight": 5464,
      "SHA256": "a5e50cbe66078249973d9a71230c4a8edbaedc26af11204042d3bce1f9ed4409"
    },
    "EXIF": {
      "Make": "Canon",
      "Model": "Canon EOS R5",
      "DateTimeOriginal": "2026:03:15 10:30:00",
      "ExposureTime": "1/1000",
      "FNumber": 2.8,
      "ISO": 100
    },
    "IPTC": {
      "By-line": "John Doe",
      "CopyrightNotice": "© 2026 John Doe"
    }
    # ... more groups: XMP, GPS, ICC_Profile, MakerNotes, Composite…
  }
}

# Remove Metadata - File Upload - Using header
curl -X POST https://exiftools.com/api/v1/remove \
  -H "X-API-Key: YOUR_API_KEY_HERE" \
  -F "[email protected]"

# Remove Metadata - File Upload - Using query parameter
curl -X POST "https://exiftools.com/api/v1/remove?key=YOUR_API_KEY_HERE" \
  -F "[email protected]"

# Remove Metadata - URL Processing - Using header
curl -X POST https://exiftools.com/api/v1/remove \
  -H "X-API-Key: YOUR_API_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/image.jpg"}'

# Remove Metadata - URL Processing - Using query parameter
curl -X POST "https://exiftools.com/api/v1/remove?key=YOUR_API_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/image.jpg"}'

# Remove Metadata - Data URL (base64) - Using header
curl -X POST https://exiftools.com/api/v1/remove \
  -H "X-API-Key: YOUR_API_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d "{\"data_url\": \"data:image/jpeg;base64,$(base64 -i image.jpg)\"}"

# Remove Metadata - Data URL (base64) - Using query parameter
curl -X POST "https://exiftools.com/api/v1/remove?key=YOUR_API_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d "{\"data_url\": \"data:image/jpeg;base64,$(base64 -i image.jpg)\"}"

# Response
{
  "success": true,
  "status": "completed",
  "uuid": "123e4567-e89b-12d3-a456-426614174000",
  "downloadUrl": "https://exiftools.com/download-cleaned/123e4567-e89b-12d3-a456-426614174000"
}
import requests

# File Upload - Using header
url = "https://exiftools.com/api/v1/extract"
headers = {
    "X-API-Key": "YOUR_API_KEY_HERE"
}
files = {
    "file": open("image.jpg", "rb")
}
response = requests.post(url, headers=headers, files=files)

# File Upload - Using query parameter
url = "https://exiftools.com/api/v1/extract?key=YOUR_API_KEY_HERE"
files = {
    "file": open("image.jpg", "rb")
}
response = requests.post(url, files=files)

# URL Processing - Using header
url = "https://exiftools.com/api/v1/extract"
headers = {
    "X-API-Key": "YOUR_API_KEY_HERE",
    "Content-Type": "application/json"
}
data = {
    "url": "https://example.com/image.jpg"
}
response = requests.post(url, headers=headers, json=data)

# URL Processing - Using query parameter
url = "https://exiftools.com/api/v1/extract?key=YOUR_API_KEY_HERE"
headers = {
    "Content-Type": "application/json"
}
data = {
    "url": "https://example.com/image.jpg"
}
response = requests.post(url, headers=headers, json=data)

# Data URL (base64) - encode a local file - Using header
import base64
with open("image.jpg", "rb") as f:
    encoded = base64.b64encode(f.read()).decode("utf-8")
url = "https://exiftools.com/api/v1/extract"
headers = {
    "X-API-Key": "YOUR_API_KEY_HERE",
    "Content-Type": "application/json"
}
data = {
    "data_url": f"data:image/jpeg;base64,{encoded}"
}
response = requests.post(url, headers=headers, json=data)

# Data URL (base64) - encode a local file - Using query parameter
import base64
with open("image.jpg", "rb") as f:
    encoded = base64.b64encode(f.read()).decode("utf-8")
url = "https://exiftools.com/api/v1/extract?key=YOUR_API_KEY_HERE"
headers = {
    "Content-Type": "application/json"
}
data = {
    "data_url": f"data:image/jpeg;base64,{encoded}"
}
response = requests.post(url, headers=headers, json=data)

# Get results by UUID - Using header
response = requests.get('https://exiftools.com/api/v1/extract/123e4567-e89b-12d3-a456-426614174000', headers={"X-API-Key": "YOUR_API_KEY_HERE"})
metadata = response.json()

# Get results by UUID - Using query parameter
response = requests.get('https://exiftools.com/api/v1/extract/123e4567-e89b-12d3-a456-426614174000?key=YOUR_API_KEY_HERE')
metadata = response.json()

# Remove Metadata - File Upload - Using header
url = "https://exiftools.com/api/v1/remove"
headers = {
    "X-API-Key": "YOUR_API_KEY_HERE"
}
files = {
    "file": open("image.jpg", "rb")
}
response = requests.post(url, headers=headers, files=files)
result = response.json()
# Download the cleaned file
download_url = result['downloadUrl']
cleaned_file = requests.get(download_url)
with open("image_cleaned.jpg", "wb") as f:
    f.write(cleaned_file.content)

# Remove Metadata - File Upload - Using query parameter
url = "https://exiftools.com/api/v1/remove?key=YOUR_API_KEY_HERE"
files = {
    "file": open("image.jpg", "rb")
}
response = requests.post(url, files=files)
result = response.json()

# Remove Metadata - URL Processing - Using header
url = "https://exiftools.com/api/v1/remove"
headers = {
    "X-API-Key": "YOUR_API_KEY_HERE",
    "Content-Type": "application/json"
}
data = {
    "url": "https://example.com/image.jpg"
}
response = requests.post(url, headers=headers, json=data)
result = response.json()

# Remove Metadata - URL Processing - Using query parameter
url = "https://exiftools.com/api/v1/remove?key=YOUR_API_KEY_HERE"
headers = {
    "Content-Type": "application/json"
}
data = {
    "url": "https://example.com/image.jpg"
}
response = requests.post(url, headers=headers, json=data)
result = response.json()

# Remove Metadata - Data URL (base64) - Using header
import base64
with open("image.jpg", "rb") as f:
    encoded = base64.b64encode(f.read()).decode("utf-8")
url = "https://exiftools.com/api/v1/remove"
headers = {
    "X-API-Key": "YOUR_API_KEY_HERE",
    "Content-Type": "application/json"
}
data = {
    "data_url": f"data:image/jpeg;base64,{encoded}"
}
response = requests.post(url, headers=headers, json=data)
result = response.json()

# Remove Metadata - Data URL (base64) - Using query parameter
import base64
with open("image.jpg", "rb") as f:
    encoded = base64.b64encode(f.read()).decode("utf-8")
url = "https://exiftools.com/api/v1/remove?key=YOUR_API_KEY_HERE"
headers = {
    "Content-Type": "application/json"
}
data = {
    "data_url": f"data:image/jpeg;base64,{encoded}"
}
response = requests.post(url, headers=headers, json=data)
result = response.json()
# Download cleaned file
cleaned_file = requests.get(result['downloadUrl'])
with open("image_cleaned.jpg", "wb") as f:
    f.write(cleaned_file.content)
// File Upload - Using header
const formData = new FormData();
formData.append('file', fileInput.files[0]);

fetch('https://exiftools.com/api/v1/extract', {
    method: 'POST',
    headers: {
        'X-API-Key': 'YOUR_API_KEY_HERE'
    },
    body: formData
})
.then(response => response.json())
.then(data => console.log(data));

// File Upload - Using query parameter
const formData2 = new FormData();
formData2.append('file', fileInput.files[0]);

fetch('https://exiftools.com/api/v1/extract?key=YOUR_API_KEY_HERE', {
    method: 'POST',
    body: formData2
})
.then(response => response.json())
.then(data => console.log(data));

// URL Processing - Using header
fetch('https://exiftools.com/api/v1/extract', {
    method: 'POST',
    headers: {
        'X-API-Key': 'YOUR_API_KEY_HERE',
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({
        url: 'https://example.com/image.jpg'
    })
})
.then(response => response.json())
.then(data => console.log(data));

// URL Processing - Using query parameter
fetch('https://exiftools.com/api/v1/extract?key=YOUR_API_KEY_HERE', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({
        url: 'https://example.com/image.jpg'
    })
})
.then(response => response.json())
.then(data => console.log(data));

// Data URL (base64) - from a File input or canvas - Using header
const reader = new FileReader();
reader.onload = () => {
    fetch('https://exiftools.com/api/v1/extract', {
        method: 'POST',
        headers: {
            'X-API-Key': 'YOUR_API_KEY_HERE',
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            data_url: reader.result // e.g. "data:image/jpeg;base64,..."
        })
    })
    .then(response => response.json())
    .then(data => console.log(data));
};
reader.readAsDataURL(fileInput.files[0]);

// Data URL (base64) - from a File input or canvas - Using query parameter
const readerQuery = new FileReader();
readerQuery.onload = () => {
    fetch('https://exiftools.com/api/v1/extract?key=YOUR_API_KEY_HERE', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            data_url: readerQuery.result // e.g. "data:image/jpeg;base64,..."
        })
    })
    .then(response => response.json())
    .then(data => console.log(data));
};
readerQuery.readAsDataURL(fileInput.files[0]);

// Get results by UUID - Using header
fetch('https://exiftools.com/api/v1/extract/123e4567-e89b-12d3-a456-426614174000', {
    headers: { 'X-API-Key': 'YOUR_API_KEY_HERE' }
})
.then(response => response.json())
.then(data => console.log(data));

// Get results by UUID - Using query parameter
fetch('https://exiftools.com/api/v1/extract/123e4567-e89b-12d3-a456-426614174000?key=YOUR_API_KEY_HERE')
.then(response => response.json())
.then(data => console.log(data));

// Remove Metadata - File Upload - Using header
const removeFormData = new FormData();
removeFormData.append('file', fileInput.files[0]);

fetch('https://exiftools.com/api/v1/remove', {
    method: 'POST',
    headers: {
        'X-API-Key': 'YOUR_API_KEY_HERE'
    },
    body: removeFormData
})
.then(response => response.json())
.then(data => {
    // Download the cleaned file
    window.location.href = data.downloadUrl;
});

// Remove Metadata - File Upload - Using query parameter
const removeFormData2 = new FormData();
removeFormData2.append('file', fileInput.files[0]);

fetch('https://exiftools.com/api/v1/remove?key=YOUR_API_KEY_HERE', {
    method: 'POST',
    body: removeFormData2
})
.then(response => response.json())
.then(data => console.log(data));

// Remove Metadata - URL Processing - Using header
fetch('https://exiftools.com/api/v1/remove', {
    method: 'POST',
    headers: {
        'X-API-Key': 'YOUR_API_KEY_HERE',
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({
        url: 'https://example.com/image.jpg'
    })
})
.then(response => response.json())
.then(data => {
    window.location.href = data.downloadUrl;
});

// Remove Metadata - URL Processing - Using query parameter
fetch('https://exiftools.com/api/v1/remove?key=YOUR_API_KEY_HERE', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify({
        url: 'https://example.com/image.jpg'
    })
})
.then(response => response.json())
.then(data => console.log(data));

// Remove Metadata - Data URL (base64) - Using header
const reader2 = new FileReader();
reader2.onload = () => {
    fetch('https://exiftools.com/api/v1/remove', {
        method: 'POST',
        headers: {
            'X-API-Key': 'YOUR_API_KEY_HERE',
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            data_url: reader2.result
        })
    })
    .then(response => response.json())
    .then(data => {
        window.location.href = data.downloadUrl;
    });
};
reader2.readAsDataURL(fileInput.files[0]);

// Remove Metadata - Data URL (base64) - Using query parameter
const reader2Query = new FileReader();
reader2Query.onload = () => {
    fetch('https://exiftools.com/api/v1/remove?key=YOUR_API_KEY_HERE', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            data_url: reader2Query.result
        })
    })
    .then(response => response.json())
    .then(data => {
        window.location.href = data.downloadUrl;
    });
};
reader2Query.readAsDataURL(fileInput.files[0]);
// File Upload - Using header
$curl = curl_init();
$file = new CURLFile('/path/to/image.jpg', 'image/jpeg', 'image.jpg');

curl_setopt_array($curl, [
    CURLOPT_URL => 'https://exiftools.com/api/v1/extract',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => [
        'file' => $file
    ],
    CURLOPT_HTTPHEADER => [
        'X-API-Key: YOUR_API_KEY_HERE'
    ]
]);

$response = curl_exec($curl);
$metadata = json_decode($response, true);
curl_close($curl);

// File Upload - Using query parameter
$curl = curl_init();
$file = new CURLFile('/path/to/image.jpg', 'image/jpeg', 'image.jpg');

curl_setopt_array($curl, [
    CURLOPT_URL => 'https://exiftools.com/api/v1/extract?key=YOUR_API_KEY_HERE',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => [
        'file' => $file
    ]
]);

$response = curl_exec($curl);
$metadata = json_decode($response, true);
curl_close($curl);

// URL Processing - Using header
$curl = curl_init();
$data = json_encode(['url' => 'https://example.com/image.jpg']);

curl_setopt_array($curl, [
    CURLOPT_URL => 'https://exiftools.com/api/v1/extract',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $data,
    CURLOPT_HTTPHEADER => [
        'X-API-Key: YOUR_API_KEY_HERE',
        'Content-Type: application/json'
    ]
]);

$response = curl_exec($curl);
$metadata = json_decode($response, true);
curl_close($curl);

// URL Processing - Using query parameter
$curl = curl_init();
$data = json_encode(['url' => 'https://example.com/image.jpg']);

curl_setopt_array($curl, [
    CURLOPT_URL => 'https://exiftools.com/api/v1/extract?key=YOUR_API_KEY_HERE',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $data,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json'
    ]
]);

$response = curl_exec($curl);
$metadata = json_decode($response, true);
curl_close($curl);

// Data URL (base64) - encode a local file - Using header
$curl = curl_init();
$base64 = base64_encode(file_get_contents('/path/to/image.jpg'));
$data = json_encode(['data_url' => 'data:image/jpeg;base64,' . $base64]);

curl_setopt_array($curl, [
    CURLOPT_URL => 'https://exiftools.com/api/v1/extract',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $data,
    CURLOPT_HTTPHEADER => [
        'X-API-Key: YOUR_API_KEY_HERE',
        'Content-Type: application/json'
    ]
]);

$response = curl_exec($curl);
$metadata = json_decode($response, true);
curl_close($curl);

// Data URL (base64) - encode a local file - Using query parameter
$curl = curl_init();
$base64 = base64_encode(file_get_contents('/path/to/image.jpg'));
$data = json_encode(['data_url' => 'data:image/jpeg;base64,' . $base64]);

curl_setopt_array($curl, [
    CURLOPT_URL => 'https://exiftools.com/api/v1/extract?key=YOUR_API_KEY_HERE',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $data,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json'
    ]
]);

$response = curl_exec($curl);
$metadata = json_decode($response, true);
curl_close($curl);

// Get results by UUID - Using header
$curl = curl_init();
curl_setopt_array($curl, [
    CURLOPT_URL => 'https://exiftools.com/api/v1/extract/123e4567-e89b-12d3-a456-426614174000',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPGET => true,
    CURLOPT_HTTPHEADER => ['X-API-Key: YOUR_API_KEY_HERE']
]);

$response = curl_exec($curl);
$metadata = json_decode($response, true);
curl_close($curl);

// Get results by UUID - Using query parameter
$curl = curl_init();
curl_setopt_array($curl, [
    CURLOPT_URL => 'https://exiftools.com/api/v1/extract/123e4567-e89b-12d3-a456-426614174000?key=YOUR_API_KEY_HERE',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPGET => true,
]);

$response = curl_exec($curl);
$metadata = json_decode($response, true);
curl_close($curl);

// Remove Metadata - File Upload - Using header
$curl = curl_init();
$file = new CURLFile('/path/to/image.jpg', 'image/jpeg', 'image.jpg');

curl_setopt_array($curl, [
    CURLOPT_URL => 'https://exiftools.com/api/v1/remove',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => [
        'file' => $file
    ],
    CURLOPT_HTTPHEADER => [
        'X-API-Key: YOUR_API_KEY_HERE'
    ]
]);

$response = curl_exec($curl);
$result = json_decode($response, true);
curl_close($curl);

// Download the cleaned file
$downloadUrl = $result['downloadUrl'];
$cleanedContent = file_get_contents($downloadUrl);
file_put_contents('image_cleaned.jpg', $cleanedContent);

// Remove Metadata - File Upload - Using query parameter
$curl = curl_init();
$file = new CURLFile('/path/to/image.jpg', 'image/jpeg', 'image.jpg');

curl_setopt_array($curl, [
    CURLOPT_URL => 'https://exiftools.com/api/v1/remove?key=YOUR_API_KEY_HERE',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => [
        'file' => $file
    ]
]);

$response = curl_exec($curl);
$result = json_decode($response, true);
curl_close($curl);

// Remove Metadata - URL Processing - Using header
$curl = curl_init();
$data = json_encode(['url' => 'https://example.com/image.jpg']);

curl_setopt_array($curl, [
    CURLOPT_URL => 'https://exiftools.com/api/v1/remove',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $data,
    CURLOPT_HTTPHEADER => [
        'X-API-Key: YOUR_API_KEY_HERE',
        'Content-Type: application/json'
    ]
]);

$response = curl_exec($curl);
$result = json_decode($response, true);
curl_close($curl);

// Remove Metadata - URL Processing - Using query parameter
$curl = curl_init();
$data = json_encode(['url' => 'https://example.com/image.jpg']);

curl_setopt_array($curl, [
    CURLOPT_URL => 'https://exiftools.com/api/v1/remove?key=YOUR_API_KEY_HERE',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $data,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json'
    ]
]);

$response = curl_exec($curl);
$result = json_decode($response, true);
curl_close($curl);

// Remove Metadata - Data URL (base64) - Using header
$curl = curl_init();
$base64 = base64_encode(file_get_contents('/path/to/image.jpg'));
$data = json_encode(['data_url' => 'data:image/jpeg;base64,' . $base64]);

curl_setopt_array($curl, [
    CURLOPT_URL => 'https://exiftools.com/api/v1/remove',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $data,
    CURLOPT_HTTPHEADER => [
        'X-API-Key: YOUR_API_KEY_HERE',
        'Content-Type: application/json'
    ]
]);

$response = curl_exec($curl);
$result = json_decode($response, true);
curl_close($curl);

// Remove Metadata - Data URL (base64) - Using query parameter
$curl = curl_init();
$base64 = base64_encode(file_get_contents('/path/to/image.jpg'));
$data = json_encode(['data_url' => 'data:image/jpeg;base64,' . $base64]);

curl_setopt_array($curl, [
    CURLOPT_URL => 'https://exiftools.com/api/v1/remove?key=YOUR_API_KEY_HERE',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $data,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/json'
    ]
]);

$response = curl_exec($curl);
$result = json_decode($response, true);
curl_close($curl);

// Download cleaned file
$cleanedContent = file_get_contents($result['downloadUrl']);
file_put_contents('image_cleaned.jpg', $cleanedContent);
require 'net/http'
require 'json'
require 'uri'

# File Upload - Using header
uri = URI('https://exiftools.com/api/v1/extract')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri)
request['X-API-Key'] = 'YOUR_API_KEY_HERE'

# Create multipart form data
form_data = [['file', File.open('image.jpg', 'rb')]]
request.set_form(form_data, 'multipart/form-data')

response = http.request(request)
metadata = JSON.parse(response.body)

# File Upload - Using query parameter
uri = URI('https://exiftools.com/api/v1/extract?key=YOUR_API_KEY_HERE')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri)
form_data = [['file', File.open('image.jpg', 'rb')]]
request.set_form(form_data, 'multipart/form-data')

response = http.request(request)
metadata = JSON.parse(response.body)

# URL Processing - Using header
uri = URI('https://exiftools.com/api/v1/extract')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri)
request['X-API-Key'] = 'YOUR_API_KEY_HERE'
request['Content-Type'] = 'application/json'
request.body = { url: 'https://example.com/image.jpg' }.to_json

response = http.request(request)
metadata = JSON.parse(response.body)

# URL Processing - Using query parameter
uri = URI('https://exiftools.com/api/v1/extract?key=YOUR_API_KEY_HERE')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request.body = { url: 'https://example.com/image.jpg' }.to_json

response = http.request(request)
metadata = JSON.parse(response.body)

# Data URL (base64) - encode a local file - Using header
require 'base64'
encoded = Base64.strict_encode64(File.binread('image.jpg'))
uri = URI('https://exiftools.com/api/v1/extract')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri)
request['X-API-Key'] = 'YOUR_API_KEY_HERE'
request['Content-Type'] = 'application/json'
request.body = { data_url: "data:image/jpeg;base64,#{encoded}" }.to_json

response = http.request(request)
metadata = JSON.parse(response.body)

# Data URL (base64) - encode a local file - Using query parameter
require 'base64'
encoded = Base64.strict_encode64(File.binread('image.jpg'))
uri = URI('https://exiftools.com/api/v1/extract?key=YOUR_API_KEY_HERE')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request.body = { data_url: "data:image/jpeg;base64,#{encoded}" }.to_json

response = http.request(request)
metadata = JSON.parse(response.body)

# Alternative using HTTParty gem (if available)
# require 'httparty'
# 
# # File Upload
# response = HTTParty.post('https://exiftools.com/api/v1/extract',
#   headers: { 'X-API-Key' => 'YOUR_API_KEY_HERE' },
#   body: { file: File.open('image.jpg', 'rb') }
# )
# 
# # URL Processing
# response = HTTParty.post('https://exiftools.com/api/v1/extract',
#   headers: { 
#     'X-API-Key' => 'YOUR_API_KEY_HERE',
#     'Content-Type' => 'application/json'
#   },
#   body: { url: 'https://example.com/image.jpg' }.to_json
# )

# Get results by UUID - Using header
uri = URI('https://exiftools.com/api/v1/extract/123e4567-e89b-12d3-a456-426614174000')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Get.new(uri)
request['X-API-Key'] = 'YOUR_API_KEY_HERE'
response = http.request(request)
metadata = JSON.parse(response.body)

# Get results by UUID - Using query parameter
uri = URI('https://exiftools.com/api/v1/extract/123e4567-e89b-12d3-a456-426614174000?key=YOUR_API_KEY_HERE')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Get.new(uri)
response = http.request(request)
metadata = JSON.parse(response.body)

# Remove Metadata - File Upload - Using header
uri = URI('https://exiftools.com/api/v1/remove')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri)
request['X-API-Key'] = 'YOUR_API_KEY_HERE'

# Create multipart form data
form_data = [['file', File.open('image.jpg', 'rb')]]
request.set_form(form_data, 'multipart/form-data')

response = http.request(request)
result = JSON.parse(response.body)

# Download the cleaned file
download_uri = URI(result['downloadUrl'])
cleaned_file = Net::HTTP.get(download_uri)
File.write('image_cleaned.jpg', cleaned_file)

# Remove Metadata - File Upload - Using query parameter
uri = URI('https://exiftools.com/api/v1/remove?key=YOUR_API_KEY_HERE')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri)
form_data = [['file', File.open('image.jpg', 'rb')]]
request.set_form(form_data, 'multipart/form-data')

response = http.request(request)
result = JSON.parse(response.body)

# Remove Metadata - URL Processing - Using header
uri = URI('https://exiftools.com/api/v1/remove')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri)
request['X-API-Key'] = 'YOUR_API_KEY_HERE'
request['Content-Type'] = 'application/json'
request.body = { url: 'https://example.com/image.jpg' }.to_json

response = http.request(request)
result = JSON.parse(response.body)

# Remove Metadata - URL Processing - Using query parameter
uri = URI('https://exiftools.com/api/v1/remove?key=YOUR_API_KEY_HERE')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request.body = { url: 'https://example.com/image.jpg' }.to_json

response = http.request(request)
result = JSON.parse(response.body)

# Remove Metadata - Data URL (base64) - Using header
require 'base64'
encoded = Base64.strict_encode64(File.binread('image.jpg'))
uri = URI('https://exiftools.com/api/v1/remove')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri)
request['X-API-Key'] = 'YOUR_API_KEY_HERE'
request['Content-Type'] = 'application/json'
request.body = { data_url: "data:image/jpeg;base64,#{encoded}" }.to_json

response = http.request(request)
result = JSON.parse(response.body)

# Remove Metadata - Data URL (base64) - Using query parameter
require 'base64'
encoded = Base64.strict_encode64(File.binread('image.jpg'))
uri = URI('https://exiftools.com/api/v1/remove?key=YOUR_API_KEY_HERE')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request.body = { data_url: "data:image/jpeg;base64,#{encoded}" }.to_json

response = http.request(request)
result = JSON.parse(response.body)

# Download cleaned file
download_uri = URI(result['downloadUrl'])
cleaned_file = Net::HTTP.get(download_uri)
File.write('image_cleaned.jpg', cleaned_file)