Logo
  • Home
  • Blog
  • Developers
  • Pricing
  • FAQ
  • Contact
Sign InSign Up
Logo

Transform your videos with our powerful API. Trim, convert, add subtitles, overlay watermarks, and more. Simple pricing, powerful features.

© Copyright 2026 Video Composer. All Rights Reserved.

Product
  • All Tools
  • Pricing
  • API Docs
  • Docs
Tools
  • MP4 to GIF
  • Video to GIF
  • Video Converter
  • Video Trimmer
  • Video Cutter
  • MP4 Cutter
  • Online Video Cutter
  • Merge Videos
  • Add Watermark to Video
Resources
  • Blog
  • Guides
  • Comparisons
  • Use Cases
  • Alternatives
  • FAQ
  • Convert MP4 to GIF
  • Merge Videos With Audio
  • Make a GIF from Video
  • How to Trim a Video
  • How to Cut MP4
  • Add Logo Watermark Guide
Compare
  • vs Shotstack
  • vs Clideo
  • Clideo Alternative
  • Kapwing Alternative
  • VEED Alternative
  • Social Media Videos
  • Ecommerce Videos
Blog
  • How to Merge Videos Free
  • Free MP4 Cutter Online
  • Merge Videos With Subtitles
  • Best Free Video Mergers 2026
  • Video Processing API Guide
  • Add Watermark via API
  • Add Subtitles via API
  • Batch Process Videos API
About
  • Contact
Legal
  • Terms of Service
  • Privacy Policy
  • Cookie Policy

How to Add a Watermark to Videos Using an API — Developer Tutorial

Mar 8, 2026

Learn how to programmatically add watermarks to videos using the VideoComposer API. Code examples in curl, Node.js, and Python for branding at scale.

Cover Image for How to Add a Watermark to Videos Using an API — Developer Tutorial

How Do You Add a Watermark to a Video Using an API?

You can add watermarks to videos programmatically using the VideoComposer API's /api/v1/watermark endpoint. Send your video file and watermark image via a POST request, specify position and opacity, and receive a watermarked output. This tutorial walks through the full implementation in curl, Node.js, and Python. Full API documentation is at /developers.


Why Add Watermarks to Videos Programmatically?

Manual watermarking in video editors does not scale. When you need consistent branding across dozens or hundreds of videos, an API-based approach is the only viable solution.

Key reasons to use a video watermark API:

  • Brand consistency at scale — every video gets the same logo, same position, same opacity without manual steps
  • Batch processing — apply watermarks to an entire library or all new uploads in a single pipeline run
  • Automated workflows — trigger watermarking on video upload events, schedule runs overnight, or integrate into CI/CD pipelines for video content
  • No manual editing — eliminate hours of repetitive work in Premiere, DaVinci, or iMovie for large video catalogs

What Do You Need Before You Start?

Before making your first API call, have these two things ready:

  1. An API key — generate one from the developers page. Your key goes in the Authorization header as a Bearer token.
  2. A watermark image — use a PNG with a transparent background. Transparency support is what makes a logo sit cleanly on video without a white box behind it.

You do not need to install any video libraries or configure codecs. The API handles all processing server-side.


Step 1: Basic Watermark API Call With curl

The simplest watermark request sends your video file and watermark image together. The position parameter controls placement, and opacity controls how transparent the overlay appears.

curl -X POST https://videocomposer.io/api/v1/watermark \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@video.mp4" \
  -F "watermark=@logo.png" \
  -F "position=bottom-right" \
  -F "opacity=0.85" \
  -F "output_format=mp4"

The response includes a download_url for the processed file and a job_id for status polling if the file is large. For a full list of parameters and response schemas, see the API reference at /developers.


Step 2: Node.js Implementation

This example uses the built-in fetch API available in Node.js 18+. No extra dependencies are needed beyond form-data for the multipart upload.

import { readFileSync } from 'fs';
import FormData from 'form-data';

const API_KEY = process.env.VIDEOCOMPOSER_API_KEY;
const API_URL = 'https://videocomposer.io/api/v1/watermark';

async function addWatermark(videoPath, watermarkPath, position = 'bottom-right') {
  const form = new FormData();
  form.append('file', readFileSync(videoPath), { filename: 'video.mp4' });
  form.append('watermark', readFileSync(watermarkPath), { filename: 'logo.png' });
  form.append('position', position);
  form.append('opacity', '0.85');
  form.append('output_format', 'mp4');

  const response = await fetch(API_URL, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      ...form.getHeaders(),
    },
    body: form,
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`API error ${response.status}: ${error.message}`);
  }

  const result = await response.json();
  console.log('Download URL:', result.download_url);
  return result;
}

// Usage
addWatermark('./source.mp4', './logo.png', 'bottom-right');

Store your API key in an environment variable — never hardcode credentials in source files. The example reads from process.env.VIDEOCOMPOSER_API_KEY.


Step 3: Python Implementation

This example uses the requests library, which is the standard HTTP client for Python.

import os
import requests

API_KEY = os.environ.get("VIDEOCOMPOSER_API_KEY")
API_URL = "https://videocomposer.io/api/v1/watermark"

def add_watermark(video_path: str, watermark_path: str, position: str = "bottom-right") -> dict:
    headers = {
        "Authorization": f"Bearer {API_KEY}",
    }

    with open(video_path, "rb") as video_file, open(watermark_path, "rb") as watermark_file:
        files = {
            "file": ("video.mp4", video_file, "video/mp4"),
            "watermark": ("logo.png", watermark_file, "image/png"),
        }
        data = {
            "position": position,
            "opacity": "0.85",
            "output_format": "mp4",
        }

        response = requests.post(API_URL, headers=headers, files=files, data=data)

    response.raise_for_status()  # raises HTTPError for 4xx/5xx responses
    result = response.json()
    print(f"Download URL: {result['download_url']}")
    return result


# Usage
add_watermark("source.mp4", "logo.png", "bottom-right")

The raise_for_status() call ensures exceptions are raised for error responses. Wrap this in a try/except block in production to handle failures gracefully.


What Watermark Positions Are Available?

The position parameter accepts five placement values. Choose based on where your brand identity sits in your design system.

Position ValuePlacementCommon Use Case
top-leftUpper left cornerNews-style lower-thirds inverted for branding
top-rightUpper right cornerChannel branding for streaming content
bottom-leftLower left cornerAttribution or source credit
bottom-rightLower right cornerMost common brand logo placement
centerCenter of frameCopyright protection overlays

All positions respect a default margin from the video edges. The opacity parameter accepts values from 0.0 (fully transparent) to 1.0 (fully opaque). A value of 0.8–0.9 is typical for brand logos.


How Do You Watermark Multiple Videos in a Batch?

For batch watermarking, loop over your video files and submit each one to the API. Use async job IDs to track progress rather than waiting synchronously for each file.

Node.js batch watermarking example:

import { readFileSync } from 'fs';
import { readdir } from 'fs/promises';
import path from 'path';
import FormData from 'form-data';

const API_KEY = process.env.VIDEOCOMPOSER_API_KEY;

async function submitWatermarkJob(videoPath, watermarkPath) {
  const form = new FormData();
  form.append('file', readFileSync(videoPath), { filename: path.basename(videoPath) });
  form.append('watermark', readFileSync(watermarkPath), { filename: 'logo.png' });
  form.append('position', 'bottom-right');
  form.append('opacity', '0.85');
  form.append('async', 'true'); // non-blocking — returns job_id immediately

  const response = await fetch('https://videocomposer.io/api/v1/watermark', {
    method: 'POST',
    headers: { Authorization: `Bearer ${API_KEY}`, ...form.getHeaders() },
    body: form,
  });

  const result = await response.json();
  return result.job_id;
}

async function pollJobStatus(jobId) {
  const url = `https://videocomposer.io/api/v1/jobs/${jobId}`;
  while (true) {
    const response = await fetch(url, {
      headers: { Authorization: `Bearer ${API_KEY}` },
    });
    const job = await response.json();
    if (job.status === 'complete') return job.download_url;
    if (job.status === 'failed') throw new Error(`Job ${jobId} failed: ${job.error}`);
    await new Promise((r) => setTimeout(r, 5000)); // poll every 5 seconds
  }
}

async function batchWatermark(videoDir, watermarkPath) {
  const files = (await readdir(videoDir)).filter((f) => f.endsWith('.mp4'));
  console.log(`Submitting ${files.length} watermark jobs...`);

  // Submit all jobs concurrently
  const jobIds = await Promise.all(
    files.map((file) => submitWatermarkJob(path.join(videoDir, file), watermarkPath))
  );

  // Poll for completion
  const downloadUrls = await Promise.all(jobIds.map(pollJobStatus));
  console.log('All jobs complete. Download URLs:', downloadUrls);
  return downloadUrls;
}

batchWatermark('./videos', './logo.png');

Set async=true on each request so jobs are queued immediately rather than blocking. This lets you submit dozens of jobs in parallel and then poll for results. Check /pricing for concurrent job limits on your plan.


What Are the Best Practices for Video Watermarking?

Following these practices avoids the most common watermarking mistakes in production pipelines.

  1. Use transparent PNG files — watermark images with a solid white or black background will obscure video content. Export your logo as PNG-24 with alpha channel transparency.
  2. Size the watermark proportionally — a watermark that is 10–15% of the video width reads clearly without dominating the frame. Very large watermarks frustrate viewers.
  3. Choose a corner that does not conflict with subtitles or UI — bottom-center is used by most subtitle tracks; bottom-right clears that space. Top-left and top-right are usually safe choices.
  4. Test on a short clip before batch runs — submit one 10-second test clip to verify position and opacity before processing a large library. This saves time and API credits.
  5. Handle errors explicitly — API requests can fail due to network issues, unsupported formats, or file size limits. Implement retry logic with exponential backoff and log job IDs for failed requests so you can reprocess them.

API vs. Manual Watermarking: Which Should You Use?

Both approaches have valid use cases. The right choice depends on volume and workflow context.

FactorManual Editing (Premiere, DaVinci, iMovie)VideoComposer API
Setup timeImmediate — open editor, apply30-60 minutes to integrate
Time per video2-5 minutes per videoUnder 1 minute per video at scale
Batch processingNot practical beyond 5-10 videosBuilt-in — loop hundreds of files
ConsistencyDepends on manual steps each timeIdentical output every run
AutomationNot possibleTrigger on upload, schedule runs
CostEditor software licensePer-operation API pricing
Technical skillLow — visual toolsModerate — code required
Best forOne-off branding needs, ad hoc workOngoing pipelines, large catalogs

For teams producing more than a handful of branded videos per week, the API approach pays off quickly in time saved. The browser-based watermark tool is the right choice for quick one-off needs — no code required.


Frequently Asked Questions

What image formats work for watermarks?

PNG is the recommended format because it supports alpha channel transparency, which lets the watermark sit cleanly over video without a solid background box. JPEG watermarks are also accepted but lack transparency support — the entire bounding box of the image will appear on the video.

Can I add text watermarks instead of image watermarks?

The /api/v1/watermark endpoint accepts image files. For text-based watermarks, you can pre-render your text as a PNG with a transparent background using a tool like ImageMagick or the HTML Canvas API, then pass that PNG to the watermark endpoint. Alternatively, the subtitle burn-in endpoint supports text overlays — see the API developer guide for details.

What is the maximum video file size?

File size limits vary by plan. For large files, use the async mode with async=true to avoid HTTP timeout issues. The async response returns a job_id immediately, and you can poll for completion or use a webhook. See /pricing for limits by plan tier.

Does the free tier support watermarking?

The browser-based watermark tool at /tools/add-watermark-to-video is available free in your browser without an API key. API access for programmatic watermarking is available on paid plans. Check /pricing for current plan details.

How long does video watermark processing take?

Processing time scales with file size and resolution. A standard 1080p clip under 100 MB typically completes in under 30 seconds. Longer or higher-resolution files take proportionally more time. Use async mode with polling or webhooks for files over 100 MB to avoid request timeouts.

Can I remove existing watermarks from videos?

Watermark removal is a different operation from watermark addition and is not supported by the /api/v1/watermark endpoint. Programmatic removal requires inpainting or content-aware fill techniques that are outside the scope of the VideoComposer watermark API. The API is designed for adding brand overlays, not removing existing ones.


Get Started With Video Watermarking

The VideoComposer API makes programmatic watermarking straightforward: one endpoint, three parameters (file, watermark image, position), and your video is branded in under a minute.

  • No-code option — try the browser-based watermark tool immediately, no sign-up required
  • API access — get your API key and full endpoint documentation at /developers
  • Explore other tools — merge, cut, convert, and subtitle tools are available at /tools. For merging branded clips, see /tools/merge-videos
  • Check pricing — API plan details and rate limits are on the pricing page