Watermark Remover API
Remove watermarks from images programmatically with a single API call. AI-powered detection handles text watermarks, logo overlays, stamps, and tiled patterns.
Why Use This API
AI Watermark Detection
Automatically detects watermark type, position, and opacity. No manual masking or region selection required.
Text Watermark Removal
Removes text-based watermarks including copyright notices, dates, photographer names, and stock photo stamps.
Logo Overlay Removal
Cleanly removes logo overlays, brand marks, and graphical watermarks while preserving underlying image detail.
Batch Processing Support
Process multiple images programmatically. Integrate into your pipeline for automated bulk watermark removal.
Quick Start
Start removing watermarks in under a minute. Here's how:
- Get your API key — Sign up free to receive your key
- Send a request — POST an image to the endpoint
- Get the result — Receive the clean image in the response
curl -X POST https://precisioncounter.com/api/v1/remove-watermark \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "image=@watermarked-photo.jpg" \
-o clean-result.png
import requests
response = requests.post(
"https://precisioncounter.com/api/v1/remove-watermark",
headers={"Authorization": "Bearer YOUR_API_KEY"},
files={"image": open("watermarked-photo.jpg", "rb")}
)
with open("clean-result.png", "wb") as f:
f.write(response.content)
const fs = require("fs");
const FormData = require("form-data");
const form = new FormData();
form.append("image", fs.createReadStream("watermarked-photo.jpg"));
const response = await fetch(
"https://precisioncounter.com/api/v1/remove-watermark",
{
method: "POST",
headers: {
"Authorization": "Bearer YOUR_API_KEY",
...form.getHeaders()
},
body: form
}
);
const buffer = Buffer.from(await response.arrayBuffer());
fs.writeFileSync("clean-result.png", buffer);
API Reference
Base URL
https://precisioncounter.com/api/v1
Authentication
All requests require an API key passed in the Authorization header:
Authorization: Bearer YOUR_API_KEY
Remove Watermark
Removes watermarks from an uploaded image and returns the clean image.
Request Parameters
| Parameter | Type | Description |
|---|---|---|
| image required | file | Image with watermark to remove. Accepted formats: PNG, JPG, JPEG, WebP. Max size: 10 MB. |
| watermark_type optional | string | Type of watermark. Default: auto. Options: auto, text, logo, stamp. |
| quality optional | string | Output quality. Default: standard. Options: standard, hd. |
Response
200 OK — Returns the processed image as binary data with Content-Type: image/png.
Response Headers
| Header | Value |
|---|---|
| Content-Type | image/png or image/webp |
| X-Credits-Remaining | Number of API credits remaining |
| X-Processing-Time | Processing time in milliseconds |
Code Examples
Full Examples (with error handling)
curl -X POST https://precisioncounter.com/api/v1/remove-watermark \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "image=@watermarked-photo.jpg" \
-F "watermark_type=auto" \
-F "quality=hd" \
-o clean-result.png
echo "Watermark removed successfully"
import requests
import sys
API_KEY = "YOUR_API_KEY"
API_URL = "https://precisioncounter.com/api/v1/remove-watermark"
def remove_watermark(input_path, output_path="clean-result.png"):
"""Remove watermark from an image file."""
with open(input_path, "rb") as img:
response = requests.post(
API_URL,
headers={"Authorization": f"Bearer {API_KEY}"},
files={"image": img},
data={"watermark_type": "auto", "quality": "hd"}
)
if response.status_code == 200:
with open(output_path, "wb") as f:
f.write(response.content)
print(f"Saved to {output_path}")
print(f"Credits remaining: {response.headers.get('X-Credits-Remaining')}")
else:
print(f"Error {response.status_code}: {response.json()['error']}")
remove_watermark("watermarked-photo.jpg")
const fs = require("fs");
const FormData = require("form-data");
const fetch = require("node-fetch");
const API_KEY = "YOUR_API_KEY";
const API_URL = "https://precisioncounter.com/api/v1/remove-watermark";
async function removeWatermark(inputPath, outputPath = "clean-result.png") {
const form = new FormData();
form.append("image", fs.createReadStream(inputPath));
form.append("watermark_type", "auto");
form.append("quality", "hd");
const response = await fetch(API_URL, {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
...form.getHeaders()
},
body: form
});
if (response.ok) {
const buffer = Buffer.from(await response.arrayBuffer());
fs.writeFileSync(outputPath, buffer);
console.log(`Saved to ${outputPath}`);
console.log(`Credits: ${response.headers.get("x-credits-remaining")}`);
} else {
const error = await response.json();
console.error(`Error ${response.status}: ${error.error}`);
}
}
removeWatermark("watermarked-photo.jpg");
<?php
$api_key = "YOUR_API_KEY";
$url = "https://precisioncounter.com/api/v1/remove-watermark";
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer $api_key"
],
CURLOPT_POSTFIELDS => [
"image" => new CURLFile("watermarked-photo.jpg"),
"watermark_type" => "auto",
"quality" => "hd"
]
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200) {
file_put_contents("clean-result.png", $response);
echo "Watermark removed successfully\n";
} else {
echo "Error $httpCode: $response\n";
}
?>
package main
import (
"bytes"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
)
func removeWatermark(inputPath, outputPath string) error {
file, _ := os.Open(inputPath)
defer file.Close()
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
part, _ := writer.CreateFormFile("image", inputPath)
io.Copy(part, file)
writer.WriteField("watermark_type", "auto")
writer.WriteField("quality", "hd")
writer.Close()
req, _ := http.NewRequest("POST",
"https://precisioncounter.com/api/v1/remove-watermark", body)
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
req.Header.Set("Content-Type", writer.FormDataContentType())
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode == 200 {
out, _ := os.Create(outputPath)
defer out.Close()
io.Copy(out, resp.Body)
fmt.Printf("Saved to %s\n", outputPath)
}
return nil
}
func main() {
removeWatermark("watermarked-photo.jpg", "clean-result.png")
}
require "net/http"
require "uri"
api_key = "YOUR_API_KEY"
uri = URI("https://precisioncounter.com/api/v1/remove-watermark")
form_data = [
["image", File.open("watermarked-photo.jpg", "rb")],
["watermark_type", "auto"],
["quality", "hd"]
]
req = Net::HTTP::Post.new(uri)
req["Authorization"] = "Bearer #{api_key}"
req.set_form(form_data, "multipart/form-data")
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(req)
end
if res.code == "200"
File.binwrite("clean-result.png", res.body)
puts "Watermark removed successfully"
else
puts "Error #{res.code}: #{res.body}"
end
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_API_KEY");
using var form = new MultipartFormDataContent();
var imageContent = new ByteArrayContent(File.ReadAllBytes("watermarked-photo.jpg"));
imageContent.Headers.ContentType = new("image/jpeg");
form.Add(imageContent, "image", "watermarked-photo.jpg");
form.Add(new StringContent("auto"), "watermark_type");
form.Add(new StringContent("hd"), "quality");
var response = await client.PostAsync(
"https://precisioncounter.com/api/v1/remove-watermark", form);
if (response.IsSuccessStatusCode)
{
var result = await response.Content.ReadAsByteArrayAsync();
File.WriteAllBytes("clean-result.png", result);
Console.WriteLine("Watermark removed successfully");
}
Error Handling
The API returns standard HTTP status codes with JSON error bodies:
| Status | Meaning | Description |
|---|---|---|
| 200 | Success | Image processed successfully. Response body is the output image. |
| 400 | Bad Request | Missing image file, unsupported format, or file too large. |
| 401 | Unauthorized | Missing or invalid API key. |
| 429 | Rate Limited | Too many requests. Wait and retry with exponential backoff. |
| 500 | Server Error | Internal processing error. Retry the request. |
Error Response Format
{
"error": "Invalid file format. Accepted: png, jpg, jpeg, webp",
"code": "INVALID_FORMAT",
"status": 400
}
Rate Limits
| Plan | Requests / Minute | Max File Size | Max Resolution |
|---|---|---|---|
| Free | 10 | 10 MB | 4096 x 4096 px |
| Pro | 60 | 25 MB | 8192 x 8192 px |
Rate limit headers are included in every response:
X-RateLimit-Limit: 10 X-RateLimit-Remaining: 7 X-RateLimit-Reset: 1708646400
Use Cases
- Stock photo processing
- Document declassification
- E-commerce product cleanup
- Social media content
- Real estate photo editing
- Academic research images
- Print production
- Digital asset management
Pricing
Get free API credits when you sign up. No credit card required.
Frequently Asked Questions
quality: "hd" parameter and specify the watermark_type if known.watermark_type to auto for best results, as the AI will identify the repeating pattern and remove all instances.