Unmarkr logoUnmarkr
Developer API

Remove watermarks with one API call

Send an image, get a clean one back — visible AI logos and hidden tags removed. Not a developer? Use the free web tool.

Easy to integrate

One endpoint, no SDK required. Here's what to know:

Source image

Upload the image as multipart form-data (PNG, JPG or WebP, up to 25 MB).

Result

The cleaned image bytes are returned directly, plus an X-Unmarkr-Removed header listing what was removed.

Resolution

standard keeps your original resolution with no recompression. full rebuilds the image and returns it at high resolution.

What it removes

Visible logos (like Gemini’s sparkle), hidden AI tags, and Google’s invisible SynthID watermark.

Get started

  1. 1

    Get your API key

    Create a key in your dashboard. API calls spend credits — subscribe (Basic/Pro/Creator) or buy a one-time credit pack.

  2. 2

    Use a code sample

    Copy one of the samples below and drop in your key.

  3. 3

    Read the reference

    Check the parameters, response and limits in the reference section.

Sample code

Send an image file (replace unmarkr_live_xxx with your key):

curl -X POST https://unmarkr.io/api/remove \
  -H "Authorization: Bearer unmarkr_live_xxx" \
  -F "image=@photo.png" \
  -F "mode=standard" \
  -o clean.png

Output & resolution

The cleaned image is returned in the same format you sent. Resolution depends on your access:

TierFormatMax resolution
Free web toolPNG / JPG / WebPPreview (~0.25 MP)
API / HD (credits)PNG / JPG / WebPOriginal (standard) · high-res (full)

PNG keeps transparency and is lossless; JPG/WebP are smaller. Output format matches the input.

API reference

One endpoint cleans an image. Send it as multipart form-data, get the cleaned bytes back.

Endpoint

POST https://unmarkr.io/api/remove

Authentication

Send your secret key as a bearer token. Create one in your dashboard and keep it server-side.

Authorization: Bearer unmarkr_live_xxx

Request parameters

Body is multipart/form-data.

ParameterTypeRequiredDefaultDescription
imagefileRequiredThe image to clean — PNG, JPG or WebP.
modestringOptionalstandardWhich removal to run — standard or full. See Modes below.

Modes

Pick standard (the default) or full:

modeRemovesCreditsReturns
standardVisible logos & badges + hidden AI tags (C2PA, “Made with AI”, EXIF/XMP).1Your cleaned image
fullEverything in standard, plus the invisible SynthID watermark.8A job to check back on

standard returns your cleaned image straight away. full also removes Google’s invisible SynthID watermark — that takes a little longer, so instead of the image it returns a job you check back on.

Full removal (checking back)

Send mode=full and you get a 202 with a job to follow:

{ "jobId": "…", "status": "processing",
  "poll": "/api/jobs/…", "result": "/api/jobs/…/result" }
  1. 1. Poll GET /api/jobs/<id> with the same API key until status is done (usually well under a minute).
  2. 2. Download the cleaned image from GET /api/jobs/<id>/result.
  3. 3. If a full removal fails, your credits are refunded automatically.

Response

For standard, 200 OK returns the cleaned image bytes directly (same format you sent, no JSON wrapper). For full, you get 202 with the job JSON above. On any error, the body is a JSON object — see Errors & retries.

Response headers

HeaderDescription
Content-TypeFormat of the cleaned image, matching your input (e.g. image/png).
X-Unmarkr-RemovedComma-separated list of what was removed, e.g. Gemini sparkle, metadata:c2pa.

Credits

standard costs 1 credit per image; full costs 4 credits. Subscription credits refill monthly; purchased credits never expire. A 402means you're out of credits.

Error format

Errors return a JSON body with a human-readable error message (and sometimes a machine-readable code):

{
  "error": "Out of credits. Buy a credit pack or subscribe to continue.",
  "code": "no_credits"
}

Rate limit

Requests are limited per API key (default 60 / minute). Exceeding it returns 429 Too Many Requests with a Retry-After header (seconds to wait). Need higher limits? Contact us.

Errors & retries

StatusMeaning
401Missing or invalid API key.
402Out of credits — buy credits or subscribe.
413Image exceeds the 25 MB limit.
429Rate limit exceeded — wait Retry-After seconds.
503Full removal temporarily unavailable — try standard.
5xxTemporary engine error — retry with backoff.

Exponential backoff

For 5xx errors, retry with increasing delays (don't retry 429 immediately — honour Retry-After):

import time, requests

def remove(path, key, attempts=4):
    for i in range(attempts):
        r = requests.post(
            "https://unmarkr.io/api/remove",
            headers={"Authorization": f"Bearer {key}"},
            files={"image": open(path, "rb")},
        )
        if r.status_code < 500:
            return r
        time.sleep(2 ** i)  # 1s, 2s, 4s, 8s
    r.raise_for_status()

Ready to build?

Grab a key and make your first request in minutes.

Get your API key