How to Watermark Images in PHP
Brand your images in Laravel, Symfony, or vanilla PHP without battling the infamous 'Allowed memory size exhausted' fatal error.

Beating PHP's Memory Constraints
If you've ever tried to watermark a 10MB JPEG taken from a modern iPhone using standard PHP `imagecreatefromjpeg()` (GD) or `Imagick`, you likely hit an `Allowed memory size of X bytes exhausted` error. Uncompressing a 10MB JPEG into memory takes over 150MB of RAM, instantly killing standard Apache/PHP-FPM worker instances. Offloading to an API solves this instantly.
Step by step
Drop this into your project today
- 1
1. Skip Local Processing
Instead of moving the `$_FILES` temporary upload to your server to process it locally, stream it directly to our API.
- 2
2. Configure the HTTP Client
Use Laravel's HTTP Client, Guzzle, or standard `curl_init()` to send the file and your visual configurations.
- 3
3. Save the Output
Download the returned string directly to your public storage or AWS S3 bucket configured in your PHP app.
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
$client = new Client();
$apiKey = getenv('API_WATERMARK_KEY');
try {
$response = $client->request('POST', 'https://apiwatermark.com/api/watermark', [
'headers' => [
'Authorization' => 'Bearer ' . $apiKey,
],
'multipart' => [
[
'name' => 'image',
'contents' => fopen('/path/to/uploaded/file.jpg', 'r')
],
[
'name' => 'text',
'contents' => '© Copyright 2026'
],
[
'name' => 'position',
'contents' => 'center'
]
]
]);
file_put_contents('/path/to/output/watermarked-file.jpg', $response->getBody()->getContents());
$data = json_decode($response->getBody(), true);
// Output URL from API
echo "Secured Image: " . $data['output_url'];
} catch (\GuzzleHttp\Exception\GuzzleException $e) {
echo "Error processing image: " . $e->getMessage();
}
?>FAQ
Developer questions
Is this faster than using Imagick locally?
+
Can I use an image logo instead of text?
+
Watermark images from PHP today
Stop maintaining PHP media pipelines. Free tier covers 100 calls a month.