HomeDocsNode.js guide
Node.js guide · Images

How to Watermark Images in Node.js

Dynamically brand your user-uploaded images in Express, Next.js, or NestJS without crashing your Vercel or AWS Lambda instances.

Writing Node.js code with API Watermark

Why native Node.js image processing fails at scale

Using libraries like `sharp`, `jimp`, or `canvas` in Node.js seems easy at first. But in production, processing massive 4K JPEG uploads consumes hundreds of megabytes of RAM per request. If you are hosting on Serverless platforms like Vercel or AWS Lambda, this leads to immediate OOM (Out of Memory) crashes and 504 Gateway Timeouts. Offloading this to a dedicated GPU API is the only reliable way to scale.

Step by step

Drop this into your project today

  1. 1

    1. Capture the Upload

    Receive the raw image file via your standard multipart/form-data upload handler (like Multer in Express) or save it directly to an S3 bucket.

  2. 2

    2. Call the Watermark API

    Instead of running `sharp` locally, pass the image URL or base64 stream to the API Watermark endpoint along with your desired logo URL and opacity.

  3. 3

    3. Serve the Result

    The API returns the watermarked image stream in milliseconds. You can pipe this directly back to the client or save it to your CDN.

Watermark an Image (Using Axios in Node.js)
const fs = require('fs');
const FormData = require('form-data');

async function processImage() {
  const form = new FormData();
  form.append('image', fs.createReadStream('./raw-upload.jpg'));
  form.append('type', 'text');
  form.append('text', '@Username123 generated');
  form.append('position', 'bottom-right');
  form.append('opacity', '0.7');
  form.append('color', '#ffffff');

  const response = await fetch('https://apiwatermark.com/api/watermark', {
    method: 'POST',
    headers: {
      Authorization: 'Bearer ' + process.env.API_WATERMARK_KEY,
    },
    body: form,
  });

  if (!response.ok) {
    throw new Error(await response.text());
  }

  const buffer = Buffer.from(await response.arrayBuffer());
  fs.writeFileSync('./watermarked-output.png', buffer);
}

processImage().catch(console.error);

FAQ

Developer questions

Does this work in Next.js Edge functions?

+
Yes! Because the heavy lifting is handled by our API, you can call this safely from Next.js Edge functions, Cloudflare Workers, and Deno without hitting memory limits.

Can I send raw buffers instead of URLs?

+
Absolutely. The recommended way is to pass a 'source_url' as JSON and let our server fetch it, but you can also POST multipart/form-data with the file buffer directly from memory.

How fast is the processing?

+
Typical response times for standard 1080p web images are under 300ms, making it suitable for synchronous user request flows.

Watermark images from Node.js today

Stop maintaining Node.js media pipelines. Free tier covers 100 calls a month.