Modern applications need to handle images efficiently. Whether you're building an e-commerce platform, social network, or content management system, integrating an image compression API can dramatically improve performance. This guide covers everything you need to know about API integration for image optimization.
Why Use an Image Compression API?
Before diving into implementation, let's understand why APIs are often better than local processing:
- Offload processing - Free up your servers for other tasks
- Consistent results - Get optimized images regardless of server capabilities
- Always up-to-date - Benefit from the latest compression algorithms
- Scalable - Handle spikes in image processing without infrastructure changes
Understanding the API Basics
Most image compression APIs follow a similar pattern:
- Authentication - Provide an API key with each request
- Upload - Send the image to the API endpoint
- Wait/Poll - Wait for processing or check status
- Download - Retrieve the compressed image
Here's a typical flow diagram:
[Your App] → [API: /compress] → [Processing] → [API: /download] → [Your App]
Authentication Methods
Bearer Token (Recommended)
Most APIs use Bearer token authentication:
curl -X POST https://api.octosqueeze.com/v1/compress \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "[email protected]"
API Key in Header
Some APIs accept the key in a custom header:
const response = await fetch('https://api.example.com/compress', {
headers: {
'X-API-Key': 'YOUR_API_KEY',
},
});
Security Best Practices
- Never expose API keys in client-side code
- Store keys in environment variables
- Rotate keys periodically
- Use different keys for development and production
Making Your First Request
cURL Example
curl -X POST https://api.octosqueeze.com/v1/compress \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "file=@/path/to/image.jpg" \
-F "format=webp" \
-F "mode=balanced"
PHP Example
<?php
$curl = curl_init();
$file = new CURLFile('/path/to/image.jpg', 'image/jpeg', 'image.jpg');
curl_setopt_array($curl, [
CURLOPT_URL => 'https://api.octosqueeze.com/v1/compress',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . $_ENV['OCTOSQUEEZE_API_KEY'],
],
CURLOPT_POSTFIELDS => [
'file' => $file,
'format' => 'webp',
'mode' => 'balanced',
],
]);
$response = curl_exec($curl);
$result = json_decode($response, true);
if ($result['success']) {
$downloadUrl = $result['data']['download_url'];
// Download and save the compressed image
}
Node.js Example
const FormData = require('form-data');
const fs = require('fs');
const axios = require('axios');
async function compressImage(filePath) {
const form = new FormData();
form.append('file', fs.createReadStream(filePath));
form.append('format', 'webp');
form.append('mode', 'balanced');
const response = await axios.post(
'https://api.octosqueeze.com/v1/compress',
form,
{
headers: {
Authorization: `Bearer ${process.env.OCTOSQUEEZE_API_KEY}`,
...form.getHeaders(),
},
}
);
if (response.data.success) {
// Download the compressed image
const imageResponse = await axios.get(
response.data.data.download_url,
{ responseType: 'arraybuffer' }
);
return imageResponse.data;
}
}
Python Example
import requests
import os
def compress_image(file_path, output_path):
api_key = os.environ.get('OCTOSQUEEZE_API_KEY')
with open(file_path, 'rb') as f:
response = requests.post(
'https://api.octosqueeze.com/v1/compress',
headers={'Authorization': f'Bearer {api_key}'},
files={'file': f},
data={'format': 'webp', 'mode': 'balanced'}
)
result = response.json()
if result['success']:
# Download compressed image
image_response = requests.get(result['data']['download_url'])
with open(output_path, 'wb') as out:
out.write(image_response.content)
return True
return False
Handling Responses
Success Response
{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"compressed": true,
"original_size": 2457600,
"compressed_size": 491520,
"savings_bytes": 1966080,
"savings_percent": 80,
"format": "webp",
"download_url": "https://api.octosqueeze.com/v1/download/550e8400...",
"expires_at": "2025-01-11T12:00:00Z"
}
}
Error Response
{
"success": false,
"error": {
"code": "file_too_large",
"message": "File exceeds the maximum allowed size of 50MB"
}
}
Error Handling
Implement robust error handling for production use:
async function compressWithRetry(file, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const result = await compressImage(file);
return result;
} catch (error) {
if (error.response) {
const status = error.response.status;
// Don't retry client errors
if (status >= 400 && status < 500 && status !== 429) {
throw error;
}
// Rate limited - wait and retry
if (status === 429) {
const retryAfter = error.response.headers['retry-after'] || 60;
await sleep(retryAfter * 1000);
continue;
}
}
// Wait before retrying server errors
if (attempt < maxRetries) {
await sleep(Math.pow(2, attempt) * 1000); // Exponential backoff
}
}
}
throw new Error('Max retries exceeded');
}
Batch Processing
For multiple images, use batch endpoints when available:
async function batchCompress(imageUrls) {
const response = await axios.post(
'https://api.octosqueeze.com/v1/compress-batch',
{
items: imageUrls.map((url, index) => ({
url,
image_id: `image-${index}`,
})),
options: {
format: 'webp',
mode: 'balanced',
},
},
{
headers: {
Authorization: `Bearer ${process.env.OCTOSQUEEZE_API_KEY}`,
'Content-Type': 'application/json',
},
}
);
return response.data;
}
Webhooks for Async Processing
For large files or high volumes, use webhooks:
// Submit with webhook URL
const response = await axios.post(
'https://api.octosqueeze.com/v1/compress',
{
url: 'https://example.com/large-image.jpg',
webhook_url: 'https://yourapp.com/api/compression-complete',
}
);
// Handle webhook in your app
app.post('/api/compression-complete', (req, res) => {
const { id, status, download_url } = req.body;
if (status === 'completed') {
// Download and store the compressed image
processCompletedImage(id, download_url);
}
res.sendStatus(200);
});
Rate Limiting
Respect API rate limits to avoid disruptions:
class RateLimiter {
constructor(maxRequests, perSeconds) {
this.maxRequests = maxRequests;
this.perSeconds = perSeconds;
this.requests = [];
}
async wait() {
const now = Date.now();
this.requests = this.requests.filter(
(time) => now - time < this.perSeconds * 1000
);
if (this.requests.length >= this.maxRequests) {
const oldestRequest = this.requests[0];
const waitTime = this.perSeconds * 1000 - (now - oldestRequest);
await sleep(waitTime);
}
this.requests.push(Date.now());
}
}
const limiter = new RateLimiter(60, 60); // 60 requests per minute
async function compressWithLimit(file) {
await limiter.wait();
return compressImage(file);
}
Monitoring and Logging
Track your API usage for debugging and cost management:
function logAPICall(endpoint, duration, result) {
console.log(
JSON.stringify({
timestamp: new Date().toISOString(),
endpoint,
duration_ms: duration,
success: result.success,
savings_percent: result.data?.savings_percent,
})
);
}
async function compressWithLogging(file) {
const start = Date.now();
const result = await compressImage(file);
const duration = Date.now() - start;
logAPICall('/v1/compress', duration, result);
return result;
}
Conclusion
Integrating an image compression API involves:
- Secure authentication with properly stored API keys
- Robust error handling with retries and backoff
- Rate limit awareness to avoid service disruptions
- Async processing for large workloads
- Monitoring for debugging and cost tracking
With these practices in place, you can reliably compress millions of images while keeping your application performant and your users happy.