Real-Time Conversion Progress with Server-Sent Events
When a conversion takes more than a couple of seconds — large files, batch jobs, or complex transformations — your users want to know what’s happening. Server-Sent Events (SSE) give you real-time progress updates without the complexity of WebSockets.
SSE vs Polling
Polling means your client asks “are we done yet?” every N seconds. It’s simple but wasteful — most requests return “still processing.”
SSE flips the direction. The server pushes updates to the client as they happen. One persistent HTTP connection, zero wasted requests.
| Feature | Polling | SSE |
|---|---|---|
| Connection overhead | High (new request each time) | Low (single connection) |
| Latency | Depends on poll interval | Near-instant |
| Server load | Higher | Lower |
| Implementation | Trivial | Slightly more complex |
| Browser support | Universal | Universal (EventSource API) |
How KoalaPic’s SSE Works
After submitting a conversion, connect to the progress stream:
GET /api/v1/convert/{conversion_id}/stream
The server sends events as the conversion progresses:
event: progress
data: {"step": "validating", "percent": 10}
event: progress
data: {"step": "converting", "percent": 45}
event: progress
data: {"step": "compressing", "percent": 80}
event: complete
data: {"download_url": "https://koalapic.com/dl/abc123"}
JavaScript Client
The browser’s EventSource API makes SSE simple:
function trackConversion(conversionId, apiKey) {
const url = `https://koalapic.com/api/v1/convert/${conversionId}/stream`;
const eventSource = new EventSource(url, {
headers: { 'Authorization': `Bearer ${apiKey}` }
});
eventSource.addEventListener('progress', (event) => {
const data = JSON.parse(event.data);
updateProgressBar(data.percent);
updateStatusText(data.step);
});
eventSource.addEventListener('complete', (event) => {
const data = JSON.parse(event.data);
eventSource.close();
showDownloadButton(data.download_url);
});
eventSource.addEventListener('error', (event) => {
eventSource.close();
showErrorMessage('Connection lost. Retrying...');
// Fall back to polling
pollForResult(conversionId, apiKey);
});
}
Python Client
For server-side SSE consumption:
import requests
def stream_progress(conversion_id, api_key):
url = f"https://koalapic.com/api/v1/convert/{conversion_id}/stream"
headers = {"Authorization": f"Bearer {api_key}"}
with requests.get(url, headers=headers, stream=True) as response:
for line in response.iter_lines(decode_unicode=True):
if line.startswith("data:"):
data = json.loads(line[5:].strip())
print(f"Progress: {data.get('percent', '?')}%")
Error Handling
SSE connections can drop due to network issues. Build in reconnection:
- Browser:
EventSourceauto-reconnects by default - Custom clients: Reconnect after a short delay, use the
Last-Event-IDheader to resume - Fallback: If SSE fails entirely, fall back to polling the conversion status endpoint
When to Use SSE vs Polling
- Single conversions: SSE for the best UX (instant progress updates)
- Batch jobs: SSE for overall progress, poll for individual file status
- Simple integrations: Polling if you want minimal code
Next Steps
- Read the full API documentation for SSE endpoint details
- Build a progress UI with the API playground
- Set up webhooks for server-to-server notifications