apyhub
Cover illustration for Video Watermarking: Guide Using Node.js & ApyHub API
Tutorials

Video Watermarking: Guide Using Node.js & ApyHub API

Video Watermarking: Guide Using Node.js & ApyHub API

Originally published April 2025. Updated in September 2026 with the current API endpoints, the full parameter list, and the file upload path.

TL;DR: A Node.js script that adds a text or logo watermark to any video in about 20 lines. Working code, all nine position presets, and both the URL and file upload paths.

0101 Introduction

Your videos are assets, not just content. Watermarking protects against unauthorized reuse, keeps your brand visible when a clip gets re-shared, and gives you something to point at in an ownership dispute.

Doing it yourself means running ffmpeg somewhere, keeping it patched, and handling the encoding edge cases that show up once real user uploads arrive. This tutorial does it with ApyHub's Video Watermarking API instead, called from Node.js, so the media pipeline stays someone else's problem.

Open the Video Watermarking API and grab a free key to follow along. No card required.

0202 Why Video Watermarking Matters

  • Copyright protection: marks ownership and deters unauthorized distribution.
  • Branding: a logo or handle travels with the clip wherever it gets reposted.
  • Proof of ownership: gives you a visible claim in a dispute.
  • Content monitoring: makes your footage traceable across platforms.

0303 Prerequisites

  • Node.js 18 or later. Any version with fetch built in works; the example below uses Axios, so 14+ is fine too. Download Node.js.
  • Basic JavaScript: async/await and HTTP requests.
  • An ApyHub account for an API token. The free tier needs no card. Sign up.

Tip: you can run the whole thing without writing any code first. Every ApyHub service page has a live playground, so you can paste a video URL into the Video Watermarking API and see the result before you open your editor.

  • A video and a watermark: a publicly reachable .mp4 URL and a .png or .jpg logo, or the files locally.
  • A text editor.

0404 The API in brief

The Generate Watermark For Videos API has four endpoints, one for each combination of input and output:

EndpointInputReturns
/generate-watermark-for-videos/url/downloadRemote video URLThe video as a binary stream
/generate-watermark-for-videos/url/linkRemote video URLA signed link in data
/generate-watermark-for-videos/file/downloadUploaded fileThe video as a binary stream
/generate-watermark-for-videos/file/linkUploaded fileA signed link in data

All four are POST, all four live on https://api.eu.apyhub.com/apyhub/, and all four cost 550 atoms per call. Authentication is a single apy-token header.

Use the URL endpoints when the source video already lives somewhere reachable, which is the common case for anything in object storage. Use the file endpoints when you hold the binary. Use /link rather than /download when the result is going to a browser or another service, so you are not piping a large file through your own server.

Source formats accepted: .mp4, .mkv, .avi, .mov, .flv, .3gp, .webm. Watermark images: .jpg, .jpeg, .png, .gif.

See the full request and response schema for all four endpoints

0505 Step-by-step guide to watermarking videos

Step 1: Set up your project

· bash
mkdir video-watermarking
cd video-watermarking
npm init -y

Step 2: Install dependencies

· bash
npm install axios

fs is part of Node.js core, so there is nothing to install for it.

Step 3: Write the watermarking script

Create watermarkVideo.js:

· js
const axios = require('axios');
const fs = require('fs');

const API_BASE = 'https://api.eu.apyhub.com/apyhub/generate-watermark-for-videos';

async function addWatermark(videoUrl, watermarkImageUrl, outputFileName) {
  if (!videoUrl || !watermarkImageUrl || !outputFileName) {
    throw new Error('Missing required parameters');
  }

  const response = await axios.post(
    `${API_BASE}/url/download`,
    {
      video_url: videoUrl,
      watermark_image: watermarkImageUrl,
      watermark_position: 'bottom_right',
      watermark_opacity: 0.6,
      watermark_image_size: '120x40'
    },
    {
      headers: {
        'Content-Type': 'application/json',
        'apy-token': process.env.APY_TOKEN
      },
      responseType: 'stream'
    }
  );

  const writeStream = fs.createWriteStream(`${outputFileName}.mp4`);
  response.data.pipe(writeStream);

  return new Promise((resolve, reject) => {
    writeStream.on('finish', () => resolve(`Saved ${outputFileName}.mp4`));
    writeStream.on('error', reject);
  });
}

addWatermark(
  'https://assets.apyhub.com/samples/sample.mp4',
  'https://example.com/logo.png',
  'watermarked_video'
)
  .then(console.log)
  .catch(err => console.error('Error:', err.response?.data || err.message));

Keep the token in an environment variable rather than in the file:

· bash
export APY_TOKEN="your-token-here"

Step 4: Run it

· bash
node watermarkVideo.js

The script sends the video and watermark URLs to the API, streams the response, and writes watermarked_video.mp4 to your project directory.

Step 5: Check the output

Play the file. The logo should sit in the bottom right at 60% opacity, sized 120 by 40 pixels.

If something came back that you did not expect, run the same request in the API playground with your own key. It shows the exact response, which is the fastest way to tell a bad parameter from a bad video URL.

0606 Watermark options

Every option below is a top-level field in the JSON body (or a form field, for the upload endpoints).

ParameterWhat it doesDefault
watermark_textText watermark. Required unless you send an image.none
watermark_imageLogo image, as a URL for the URL endpoints or a file for the upload endpoints. Required unless you send text.none
watermark_positionWhere the watermark sits. See the presets below.bottom_right
watermark_opacity0 to 1. Lower is more transparent.0.5
watermark_image_sizeLogo size in WxH, for example 120x40.source size
watermark_font_sizeFont size for a text watermark.24
watermark_font_colorText color, for example #ffffff.none
watermark_text_background_colorBackground behind the text, for example #000000.none
watermark_text_paddingPadding around the text.10
sizeOutput video scale in WxH, even dimensions only.source size
gif_loopLoop a GIF watermark across the whole video.false

The nine position presets

watermark_position accepts exactly these values:

top_left top_center top_right center_left center center_right bottom_left bottom_center bottom_right

Note the underscores. top-right with a hyphen is rejected.

Bottom right is the convention for branding because it clears most subtitle tracks. Center is what you want for a "draft" or "preview" stamp that should be hard to crop out.

Try the nine positions against your own video in the playground before you hard-code one.

A text watermark instead of a logo

javascript

· js
{
  video_url: 'https://assets.apyhub.com/samples/sample.mp4',
  watermark_text: 'CONFIDENTIAL',
  watermark_position: 'center',
  watermark_font_size: 48,
  watermark_font_color: '#ffffff',
  watermark_opacity: 0.4,
  watermark_text_background_color: '#000000'
}

0707 Watermarking a local file

For videos on disk, use the upload endpoint with multipart form data:

· js
const axios = require('axios');
const fs = require('fs');
const FormData = require('form-data');

async function watermarkLocalFile(videoPath, logoPath) {
  const form = new FormData();
  form.append('video', fs.createReadStream(videoPath));
  form.append('watermark_image', fs.createReadStream(logoPath));
  form.append('watermark_position', 'bottom_right');
  form.append('watermark_opacity', '0.6');

  const response = await axios.post(
    `${API_BASE}/file/link`,
    form,
    { headers: { ...form.getHeaders(), 'apy-token': process.env.APY_TOKEN } }
  );

  return response.data.data; // signed URL to the watermarked video
}

Install form-data first with npm install form-data. The /file/link endpoint returns a signed URL rather than the binary, which is usually what you want when the result goes straight to a user or into storage.

Uploads are capped per request, so for large source files use the URL endpoints and host the video somewhere reachable instead.

Start watermarking. Free tier, no card.

0808 Best practices

  • Design: a semi-transparent PNG with transparency reads better than a solid block. Opacity between 0.4 and 0.7 is visible without dominating.
  • Position: bottom right for branding, center for draft and review copies.
  • Consistency: keep the same position, size and opacity across all your videos. Put them in one config object rather than per call site.
  • Format: PNG for logos, since it keeps transparency.
  • Cost: each call is 550 atoms regardless of which endpoint you use, so watermark once and cache the result rather than re-processing on every request.

0909 Troubleshooting

  • 401: the apy-token header is missing or the token is wrong. Check it is set in your environment.
  • 400: a required field is missing or malformed. You need either watermark_text or watermark_image, and video_url must be a full URI.
  • Nothing happens on position: check for underscores. bottom_right, not bottom-right.
  • 429: you have exceeded your plan's per-second rate. Retry with exponential backoff.
  • 503: the backend is briefly unavailable. Retry after a few seconds.
  • Timeouts on large files: the /download endpoints stream the whole video back. For long videos, use /link and fetch the result separately.

1010 Going further

  • Batch processing: loop over an array of URLs, with a concurrency limit so you do not hit the rate limit.
  • Dynamic watermarks: generate per-user text or an image first, then pass it in. Useful for screener copies that identify the recipient.
  • Job-based processing: for long videos, the Generate Watermark For Videos Job API submits the work and lets you poll for the result instead of holding a connection open.
  • Related endpoints: Apply Watermark on Images for stills, Generate Video Thumbnail for preview frames, and Apply Watermark on PDF for documents.
  • The rest of the catalog: watermarking is one of 200+ APIs on the same key and the same subscription. Browse the file manipulation category for compression, conversion and metadata endpoints you can chain onto this one.

Browse the catalog

1111 Conclusion

Twenty lines of Node.js, one API call, and every video that leaves your system carries your mark. No ffmpeg build to maintain, no encoding edge cases to discover in production.

Try the Video Watermarking API. Free tier, no card.

1212 FAQ

What is video watermarking? Embedding a mark, usually a logo or text, into a video so ownership is visible wherever the file ends up.

How do I watermark a video in Node.js? Send the video URL and your watermark to the ApyHub endpoint with Axios or fetch, then stream the response to a file. The script in step 3 is the complete version.

Where can I position the watermark? Nine presets: top_left, top_center, top_right, center_left, center, center_right, bottom_left, bottom_center, bottom_right. The default is bottom_right.

Can I use text instead of a logo? Yes. Send watermark_text instead of watermark_image, with optional font size, color, padding and background color. Send one or the other.

Can I watermark local files? Yes, through the /file/download and /file/link endpoints with multipart form data. See section 07.

What video formats are supported? .mp4, .mkv, .avi, .mov, .flv, .3gp and .webm for the source. Watermark images can be .jpg, .jpeg, .png or .gif.

What does it cost? 550 atoms per call, drawn from your ApyHub subscription. The free tier covers testing without a card.

Are there file size limits? Uploads are capped per request. For larger videos, host the file and use the URL endpoints instead.

Can I set the output resolution? Yes, with size in WxH format. Dimensions must be even numbers.

Can an AI agent call this API? Yes. Every ApyHub endpoint is MCP-ready, so an agent can discover the service, read its schema and call it without a wrapper. Connect ApyHub MCP and your agent can watermark a video as one step in a longer workflow.

1313 About ApyHub

ApyHub is the distribution and consumption layer for APIs: a curated, certified catalog that developers and AI agents use as a trusted operational layer. The catalog spans 200+ APIs and 1,000+ endpoints, available under a single subscription priced in atoms, ApyHub's unified usage unit. Every API ships with machine-readable certification covering GDPR, SOC 2 and ISO 27001 alignment, and every endpoint is MCP-ready by default. ApyHub is headquartered in Amsterdam, with offices in the Netherlands, Greece and India, and serves 65,000+ monthly developer workspaces. The free tier requires no card. Building an API? Become a provider.