compress_image · POST /v1/compress · 1 credit

Image compression API for agents and pipelines.

An image compression API re-encodes a picture at a lower quality or a lighter format over HTTP, trading a controlled amount of visual fidelity for a much smaller file.

No model and no queue — this one runs an ordinary encoder on our own infrastructure, usually in under a second, and hands the compressed bytes straight back in the response.

By the imagemcpserver.com teamUpdated

Typical page weight

4K PNG, straight from upscaleheavy
Same image, WebP @ 75a fraction of it

Exact ratios depend entirely on the image — flat illustration compresses far harder than grainy photography. Run it on your own assets and read the numbers rather than trusting a marketing figure.

It returns the file, not a link

Worth knowing before you write the integration, because this is the one tool here that behaves differently from the rest. Compression returns the compressed bytes directly, as a base64 data URI in result.image. There is no hosted copy and no imageUrl field.

That is the right shape for the job — you are usually compressing in order to write the result somewhere yourself, and fetching it back from a CDN would undo part of the saving. The practical consequence is that the response body is roughly the size of the image, so decode it and move on rather than logging it.

Should you use this at all?

Ask this question in any developer forum and the top answer is the same: if you control a backend, compress the image there yourself. That answer is correct, and we are not going to pretend otherwise. Image compression is a solved problem, the good encoders are free, and a local call has no network round trip.

So the useful question is not whether this is cheaper than doing it yourself — it is not — but whether the place that needs the compression can reasonably do it.

Do it yourself

  • You already hold the bytes in a server process
  • You are compressing thousands of files in a batch job
  • You need a lossless mode, or an encoder we do not expose
  • Latency per image genuinely matters

Use this endpoint

  • An agent is optimising an asset mid-task, with no runtime of its own
  • The previous step in a chain handed you a URL, not a buffer
  • You are on a runtime where shipping a native image binary is painful
  • You want one bill and one integration for the whole image pipeline

Quality is a decision, not a default

The single biggest win in image performance is not a clever encoder — it is admitting that a 48-pixel avatar does not need the same quality budget as a full-bleed hero.

The ladder below is for WebP and JPEG only

PNG ignores the quality number completely — every value from 1 to 100 returns byte-identical output. See the next section for what actually happens to a PNG.

85–95

Hero images, product photography, anything a visitor zooms into.

Modest savings, no visible artefacts.

70–80

Body imagery, blog figures, card art. The default sits here.

The usual sweet spot for the web.

50–65

Thumbnails, avatars, list rows, anything under 200px.

Large savings; artefacts hidden by the small render size.

10–45

Placeholders and blurred previews loaded before the real asset.

Deliberately rough — these are meant to be replaced.

Three formats, and the PNG exception

WebP, JPEG and PNG. WebP is the right answer for almost everything on the web — it handles photographs and transparency both, which is the reason to prefer it over the older pair. Ask the REST endpoint for anything outside those three and it quietly returns WebP bytes anyway, so treat the list as closed.

How each output format responds to the quality setting
FormatDoes quality do anything?What you get
webpYes, across the full rangeThe default, and the one to ship. Lossy, keeps an alpha channel.
jpegYes, across the full rangeMaximum compatibility. No alpha — transparency is flattened onto a solid ground.
pngNo — the value is ignoredColour-quantised output. Much smaller than a plain PNG re-encode, but not pixel-identical.

⚠️ There is no lossless mode

WebP and JPEG are lossy by quality. PNG is lossy by colour quantisation. If a file has to come back pixel-identical to what went in, compress it yourself with a lossless encoder — this endpoint cannot do it, whatever number you pass.

The request

One required field. The input can be a URL another tool just returned, which is the usual shape at the end of a generate-edit-compress chain.

Request
curl -X POST "https://api.imagemcpserver.com/v1/compress" \
  -H "Authorization: Bearer $IMAGEMCP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "image": "https://cdn.example.com/hero-4k.png",
    "quality": 75,
    "targetFormat": "webp"
  }'

The response

Before and after sizes come back as strings alongside the bytes, so a build script can log what it saved without measuring anything itself. Note that format echoes what you asked for rather than what was encoded — the data URI prefix on image is the authority.

Response
{
  "success": true,
  "deductedCredits": 1,
  "userCredits": 2418,
  "result": {
    "image": "data:image/webp;base64,UklGRl4…",
    "originalSize": "4302.4 KB",
    "compressedSize": "380.2 KB",
    "savedPercentage": "91.2%",
    "quality": "75%",
    "format": "WEBP",
    "latency": "0.42s"
  }
}

Python and Node

Because the response carries a data URI rather than a link, both samples split the header off before decoding. That one line is the whole integration.

Python
import os, base64, requests

r = requests.post(
    "https://api.imagemcpserver.com/v1/compress",
    headers={"Authorization": f"Bearer {os.environ['IMAGEMCP_API_KEY']}"},
    json={"image": src_url, "quality": 75, "targetFormat": "webp"},
    timeout=60,
)
result = r.json()["result"]

# result.image is a data URI — split off the header before decoding
header, payload = result["image"].split(",", 1)
open("hero.webp", "wb").write(base64.b64decode(payload))
print(result["originalSize"], "->", result["compressedSize"], result["savedPercentage"])
Node
const res = await fetch("https://api.imagemcpserver.com/v1/compress", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.IMAGEMCP_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ image: srcUrl, quality: 75, targetFormat: "webp" }),
});
const { result } = await res.json();

const payload = result.image.split(",")[1];
await fs.writeFile("hero.webp", Buffer.from(payload, "base64"));
console.log(result.originalSize, "->", result.compressedSize, result.savedPercentage);

Every field

Three fields, one of them required. The same body works for the REST endpoint and the compress_image MCP tool.

Request body fields accepted by POST /v1/compress and the compress_image MCP tool
FieldAcceptsWhat it does
imagestring · requiredA public https URL or a base64 data URI — including a URL another tool just returned. imageBase64 is accepted as an alias.
qualitynumber · 1–100Encoder quality, default 70, clamped into range. Drives WebP and JPEG output. Ignored entirely for PNG.
targetFormatwebp · jpeg · pngDefaults to webp. Over REST any other value silently falls back to WebP bytes, so stay inside the set.

⚠️ Alpha and JPEG do not mix

Compressing a transparent cutout to JPEG flattens the alpha onto a solid ground. If the source has transparency, target WebP — it keeps the alpha channel and still compresses properly.

Why an agent should compress before it commits

Largest Contentful Paint

On most content pages the LCP element is an image. Its transfer size is the single lever with the most effect on that number, and it is a lever you can pull automatically.

Repository hygiene

An agent that generates assets straight into a repo can leave megabytes of PNG behind. A compress step before the write keeps the diff reviewable and the clone fast.

Bandwidth you pay for

Every uncompressed hero is served to every visitor. One credit spent once beats the same bytes shipped a hundred thousand times.

What it costs

One credit per call, flat, whatever the image weighs. No model provider is involved, which is why it is the cheapest call here.

Free

30 images

30 credits a month, no card required.

Starter · $20

2¢ each

1,000 credits — 1,000 compressions a month.

Pro · $50

≈ 1.7¢ each

3,000 credits.

Enterprise · $100

≈ 1.3¢ each

8,000 credits.

Dedicated compression services and free tiers will beat that per image, and running an encoder yourself costs nothing at all. The number that matters is whether a credit is cheaper than building somewhere for the compression to happen — see plans and credit packs.

Compression API questions

Should I use this, or just compress images myself?

If you control a backend and already have the bytes in hand, install sharp and do it there. It is free, it is faster than a network round trip, and it is the honest answer — this endpoint runs sharp too. What you are buying here is the case where that is awkward: an agent optimising an asset mid-task, a serverless runtime where shipping a native binary is painful, or a chain where the previous step handed you a URL rather than a buffer. It is a convenience inside a pipeline, not a cheaper way to run an encoder.

What comes back — a URL or the file?

The file. Unlike every other tool here, compression returns the bytes directly as a base64 data URI in result.image, with no hosted copy. That is deliberate: the point of compressing is usually to write the result somewhere yourself, and a round trip to fetch it back would undo the saving. It also means the response is large, so do not log it.

What quality setting should I use?

The default of 70 is a good starting point for photography on the web. Push to 80–85 for hero images and product shots where artefacts would be noticed; drop to 50–60 for thumbnails, avatars and anything rendered small. Values are clamped to 1–100.

Does the quality setting affect PNG output?

No, and this surprises people. For WebP and JPEG the number does exactly what you expect. For PNG it is ignored — every value from 1 to 100 produces byte-identical output. What passing it does do is trigger colour quantisation, which is why PNG output is dramatically smaller than a plain re-encode but is not pixel-identical to the source. If you need a truly lossless PNG, this endpoint is not the tool.

Which output formats can I compress to?

Three: WebP (the default), JPEG and PNG. WebP is the right answer for almost every image on the web — it handles photographs and transparency both. Ask for anything outside those three over REST and you silently get WebP bytes back, so stick to the documented set.

Is compression lossy?

Yes, in every mode this endpoint offers. WebP and JPEG are lossy by quality setting. PNG is lossy by colour quantisation rather than by quality. There is no lossless path here — if a file has to stay pixel-identical, compress it yourself with a lossless encoder.

How is this different from convert_format?

compress_image is about file size: you set a quality percentage and it re-encodes, returning bytes. convert_format is about the container: it moves an image between PNG, JPG, WebP, GIF, TIFF and AVIF without a quality dial, and returns a hosted URL. Reach for compression when the file is too heavy, conversion when the format is wrong.

Does it cost the same regardless of image size?

Yes — 1 credit per call, flat, which is between about 1.3 and 2 cents depending on your plan. No model provider is involved, which is why it is the cheapest call on the platform and typically finishes in well under a second.

Can I compress a whole batch at once?

Yes, through multicall — the calls are dispatched concurrently and billed as one deduction, at 1 credit each. Bear in mind every result carries its own base64 payload, so a large batch produces a very large response.

Reference