# PDF Watermark & Unlock PDF Tool: Stamp, Remove Password (`data-done-right/pdf-watermark-unlock`) Actor

PDF watermark and unlock PDF tool: add a text or image watermark to PDFs in bulk, add page numbers, remove a PDF password you supply, or set a password. Direct download links. Cannot crack passwords.

- **URL**: https://apify.com/data-done-right/pdf-watermark-unlock.md
- **Developed by:** [Data Done Right](https://apify.com/data-done-right) (community)
- **Categories:** Automation, Developer tools
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $6.40 / 1,000 pdf processeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## PDF Watermark & Unlock PDF Tool: Stamp Text, Add Page Numbers, Remove a Password

This **PDF watermark** and **unlock PDF** tool adds a text or image watermark to many PDFs at once, adds "Page X of Y" page numbers, removes a PDF password when you supply the correct one, and can set a password on a file. Give it links to PDFs, get back direct, signed download links. It is built for bulk work and for use through the API, Make, n8n or Zapier.

> **This tool cannot crack passwords.** It never guesses or brute-forces. To unlock a PDF you must supply the correct password. Use it only on files you own or are allowed to modify.

### How to add a watermark to a PDF

1. Paste your PDF links into **PDF URLs** (one per line).
2. Keep **Operation** on `watermark` and set **Watermark text**, for example `CONFIDENTIAL`.
3. Adjust font size, color, opacity, rotation, position (center, tiled, corners) and page range. Example: opacity `0.3`, rotation `45`, position `tiled`.
4. Run. Each output PDF appears in the dataset with a download link.

To add a logo, fill **Watermark image URL** (PNG, JPG or WebP; transparent PNGs work well). Text and image can be combined.

### How to add page numbers to a PDF

Set **Page numbers** to `footer` or `header`. The default format is `Page {page} of {total}`; change it, for example to `{page}/{total}`. Leave the watermark text empty if you only want page numbers.

### How to unlock a PDF (remove a PDF password)

1. Set **Operation** to `unlock`.
2. Enter the file's password in **PDF password**. It is stored as a secret and never logged.
3. Run. You get the same PDF without the password.

What unlock does, honestly:

- **Password you know:** removed when you supply the right one. A wrong password gives a clear error.
- **Owner restrictions** (the "no printing / no copying" flags): removed only when the file opens without a password.
- **Not protected at all:** you get status `not_protected` and are not charged.
- **Forgotten password:** not supported. This tool cannot crack passwords.

### How to remove a PDF password and set a new one

Use `protect` and give **New password**. The output is encrypted with AES-256. Combine it with a password for the source if the source is protected too.

### Input example

```json
{
  "urls": ["https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"],
  "operation": "watermark",
  "watermarkText": "CONFIDENTIAL",
  "position": "tiled",
  "opacity": 0.3,
  "rotation": 45,
  "pageNumbers": "footer"
}
```

Unlock example: `{"urls": ["https://example.com/locked.pdf"], "operation": "unlock", "password": "your-password"}`

### Output example

One dataset row per output file. Failed files get a row with `status: "error"` and an `error` message; one bad link never stops the run.

```json
{
  "sourceUrl": "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
  "fileName": "dummy-watermarked.pdf",
  "url": "https://api.apify.com/v2/key-value-stores/.../records/000-dummy-watermarked.pdf?signature=...",
  "operation": "watermark",
  "pages": 1,
  "pagesStamped": 1,
  "bytes": 13480,
  "status": "ok"
}
```

The `url` is signed, so it downloads without an API token. Files stay in the run's key-value store (or your **Output store name**) until the store expires.

### Use cases

- Stamp DRAFT, CONFIDENTIAL or a customer name on contracts, reports and invoices.
- Brand PDFs with a logo before sharing them.
- Number the pages of merged or exported documents.
- Remove a password from your own archived PDFs so they can be indexed or processed.
- Set a password on documents before sending them.

### How much does it cost

Pay per event: **$0.008 per output PDF** (`pdf-processed`), no start fee. Unlock on a file with nothing to remove is not charged. Use **Max output files** to cap spend.

### Limits

- Default 50 MB and 500 pages per file (max 200 MB). Larger files are skipped with an error.
- Links must be public and direct. Pages that need a login are not supported.
- Page numbers and watermarks are drawn on top of the page content; scanned pages are stamped but not OCR'd.
- Output of a watermark run is not password protected, even if the source was (you supply its password to open it).
- Built-in fonts cover Latin text; other scripts use DejaVu Sans automatically.

### FAQ

**Can it remove a PDF password if I forgot it?** No. It cannot crack, guess or brute-force passwords. You must supply the correct one.

**Can it remove "restrictions" such as no printing or copying?** Yes, when the file opens without a user password. Use only on files you own or may modify.

**Does the watermark change the original text?** No. The watermark is an overlay on each page; text remains selectable.

**Can I watermark only some pages?** Yes: set Page range, for example `1-3,5`, `odd` or `2-`.

**Can I put a logo on the PDF?** Yes: give a PNG, JPG or WebP link in Watermark image URL.

**Is the password logged?** No. Password fields are secret inputs and are never written to logs or output.

### Related tools

- PDF Merger & Splitter
- PDF Compressor
- PDF to Text & OCR

# Actor input Schema

## `urls` (type: `array`):

Direct links to the PDF files to process, one per line. Example: https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf. Dropbox and Google Drive share links are converted to direct downloads. Each file is handled separately; a bad link never stops the run.

## `operation` (type: `string`):

watermark = stamp text, image or page numbers. unlock = remove a password you supply (or owner restrictions on files that open without a password). protect = set a password. This tool cannot crack or guess passwords; use it only on files you own or may modify.

## `watermarkText` (type: `string`):

Text stamped on every selected page, for example CONFIDENTIAL, DRAFT or Do not copy. Leave empty to use only an image or page numbers. Used by the watermark operation.

## `watermarkImageUrl` (type: `string`):

Link to a PNG, JPG or WebP logo to stamp (up to 10 MB). Transparent PNGs work well. Example: https://example.com/logo.png. It is combined with the text if both are set.

## `position` (type: `string`):

Where the watermark goes. Tiled repeats it across the whole page.

## `fontSize` (type: `integer`):

Text size in points. Long text is shrunk automatically to fit the page. Example: 48.

## `font` (type: `string`):

Font for the watermark text. Non-Latin text (Cyrillic, Greek) switches to the Unicode font automatically.

## `color` (type: `string`):

Watermark color as a hex code. Examples: #808080 (gray), #FF0000 (red).

## `opacity` (type: `number`):

From 0 (invisible) to 1 (solid). Example: 0.3 keeps the page readable.

## `rotation` (type: `integer`):

Counter-clockwise angle. 45 is the classic diagonal, 0 is horizontal.

## `imageWidthPercent` (type: `integer`):

Size of the image watermark as a percentage of the page width. Example: 40.

## `pageRange` (type: `string`):

Pages to stamp. Examples: all, 1-3,5, 2-, odd, even. Pages outside the file are ignored.

## `pageNumbers` (type: `string`):

Add page numbers in the header or footer, on the pages in the page range.

## `pageNumberFormat` (type: `string`):

Text for the page numbers. {page} and {total} are replaced. Example: Page {page} of {total}.

## `pageNumberAlign` (type: `string`):

Horizontal position of the page numbers.

## `password` (type: `string`):

The correct password for a protected PDF. Needed for unlock on files with a user password, and to watermark or protect such files. It is never logged. If you leave it empty, only files that open without a password work. This tool cannot crack passwords.

## `newPassword` (type: `string`):

Password to set when the operation is protect. Example: a long passphrase. It is never logged.

## `ownerPassword` (type: `string`):

Optional separate owner password for protect. If empty, the new password is also the owner password.

## `maxFiles` (type: `integer`):

Hard cap on delivered PDFs per run, which also caps your cost. Example: 100.

## `maxFileSizeMb` (type: `integer`):

Files larger than this are skipped with a clear error. Maximum 200. Example: 50.

## `maxPagesPerFile` (type: `integer`):

Files with more pages are skipped. Example: 500.

## `maxConcurrency` (type: `integer`):

How many PDFs to process at the same time.

## `outputStoreName` (type: `string`):

Save the output PDFs in a named key-value store that you keep, instead of the default store of the run. Example: my-watermarked-pdfs.

## `proxyConfiguration` (type: `object`):

Only needed if a file host blocks Apify IPs. Most PDF links work without it.

## Actor input object example

```json
{
  "urls": [
    "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"
  ],
  "operation": "watermark",
  "watermarkText": "CONFIDENTIAL",
  "position": "center",
  "fontSize": 48,
  "font": "helvetica-bold",
  "color": "#808080",
  "opacity": 0.3,
  "rotation": 45,
  "imageWidthPercent": 40,
  "pageRange": "all",
  "pageNumbers": "none",
  "pageNumberFormat": "Page {page} of {total}",
  "pageNumberAlign": "center",
  "maxFiles": 100,
  "maxFileSizeMb": 50,
  "maxPagesPerFile": 500,
  "maxConcurrency": 3
}
```

# Actor output Schema

## `results` (type: `string`):

All result items of this run (the default dataset), as JSON, CSV, Excel and more.

## `records` (type: `string`):

Key-value store records: the run summary, notes on any problems, and any files.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "urls": [
        "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"
    ],
    "operation": "watermark",
    "watermarkText": "CONFIDENTIAL"
};

// Run the Actor and wait for it to finish
const run = await client.actor("data-done-right/pdf-watermark-unlock").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "urls": ["https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"],
    "operation": "watermark",
    "watermarkText": "CONFIDENTIAL",
}

# Run the Actor and wait for it to finish
run = client.actor("data-done-right/pdf-watermark-unlock").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "urls": [
    "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"
  ],
  "operation": "watermark",
  "watermarkText": "CONFIDENTIAL"
}' |
apify call data-done-right/pdf-watermark-unlock --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,data-done-right/pdf-watermark-unlock"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/XAbHrl25gzv9gXLM1/builds/SDG4MkXshe8ghy9qC/openapi.json
