The same cleaner, for your systems.

Send a file with an API key, get the clean file back. For upload forms, document pipelines and anything that cannot open a browser.

This one uploads

Unlike everything else on this site, a file sent to the API leaves your device. It is cleaned on Cloudflare's network for the length of one request: in memory up to 25 MB; above that, written to temporary R2 storage for that request and deleted as soon as the reply is sent (a one-day rule catches a dropped connection). Nothing about the file is logged; only a count of files for your quota is kept.

If a file must never leave your own servers, run the same API yourself: it is one fetch handler in the open-source repository and runs on Node, Deno, Bun or Cloudflare Workers.

Start

  1. Sign in with your email address. No password.
  2. On your account page, create a key. It is shown once.
  3. Call the API with the key as a bearer token.
curl -H "Authorization: Bearer $FILESANITY_KEY" \
  -F file=@photo.jpg \
  "https://filesanity.com/api/v1/clean" -o photo-clean.jpg -D -

Endpoints

POST /cleanThe file as a multipart part named file, or as the raw body with X-Filename. Returns the clean file. Headers X-FileSanity-Removed, -Kept and -Note say what happened.
POST /inspectSame input. Returns the report as JSON: every field found, grouped by part, and whether it would be removed.
GET /usageYour plan, files used this month, and the quota.
?keep=exif,xmpA policy: kinds of field to keep. The same keys as the batch page.
?report=1On /clean, Team and API plans: adds X-FileSanity-Report, a base64 JSON record with the clean file's SHA-256, and X-FileSanity-Report-Signature, an Ed25519 signature over it.

Files over 25 MB go as the raw body with X-Filename, not as a multipart form: curl --data-binary @scan.pdf -H "X-Filename: scan.pdf". JPEG and PDF files are read whole, so the API takes them up to 50 MB; the other formats go up to your plan's size.

All paths are under https://filesanity.com/api/v1. Errors are JSON with an error field: 401 for a missing or revoked key, 402 when the month's files are used, 411 when the request has no Content-Length (chunked uploads are not taken), 413 for a file over your plan's size, 415 for a format FileSanity does not read.

Checking a signed report

The public key is at https://filesanity.com/api/report-key. Anyone holding the clean file, the report and the signature can check that this file came out of FileSanity on that date with those fields removed, without trusting the person who sent it.

// Node 20+
const res = await fetch('https://filesanity.com/api/report-key')
const key = await crypto.subtle.importKey(
  'jwk', await res.json(), { name: 'Ed25519' }, false, ['verify'])
const report = Buffer.from(reportHeader, 'base64')
const sig = Buffer.from(signatureHeader, 'base64')
const ok = await crypto.subtle.verify('Ed25519', key, sig, report)

Quotas

Free50 files a month, up to 10 MB each
Pro1,000 files a month, up to 95 MB each (JPEG and PDF 50 MB)
Team5,000 files a month, up to 95 MB each (JPEG and PDF 50 MB)
API50,000 files a month, up to 95 MB each (JPEG and PDF 50 MB)

The count resets on the first of each month, UTC. Larger files clean in the browser, where we set no size limit.