Get Render
Retrieve the status and result of a render job.
Endpoint
GET /v1/renders/:id
Request
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | The render ID returned from POST /renders |
Headers
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer token with your API key |
Response
Success Response (200 OK)
The response varies based on the render status:
Processing
While the render is still in progress:
{
"status": "processing",
"retryAfter": 1
}
Completed
When the render has finished successfully:
{
"status": "completed",
"html": "base64-encoded-gzipped-html-content",
"loadStrategy": "default",
"selectedCity": {
"name": "new.york",
"displayName": "New York",
"latitude": 40.7128,
"longitude": -74.0060,
"timezoneId": "America/New_York"
},
"bandwidthMetrics": {
"networkBytes": 2048576,
"cachedBytes": 512000,
"cacheHitRate": "20.0%"
},
"captcha": {
"detected": false,
"handled": false
},
"timingBreakdown": {
"browserInitMs": 245,
"navigationMs": 607,
"loadStrategyMs": 156,
"captchaMs": 0,
"waitActionsMs": 0,
"screenshotMs": 0,
"htmlCaptureMs": 89,
"totalMs": 759
},
"fetchResponses": "base64-encoded-gzipped-json-array",
"screenshot": "base64-encoded-jpeg-or-png-image",
"retryAfter": 1
}
Failed
When the render has failed (HTTP 422):
{
"status": "failed",
"errorCode": "RENDER_TIMEOUT",
"errorMessage": "Overall render exceeded 120 second timeout",
"billable": true,
"charged": true,
"chargedAmountCents": 1,
"retryAfter": 1
}
The errorCode tells you exactly what went wrong, and the billable field tells you whether you were charged. System errors (billable: false) are never charged. See Error Codes Reference for all error codes and their billing classification.
Response Fields
| Field | Type | Always Present | Description |
|---|---|---|---|
status | string | Yes | Render status: processing, completed, or failed |
html | string | Completed only | Base64-encoded, gzipped HTML content |
loadStrategy | string | Completed only | Load strategy used: default (standard page stabilization) or custom (user-specified waitFor actions) |
screenshot | string | Completed only (if requested) | Base64-encoded screenshot image (JPEG or PNG). Only present if includeScreenshot: true was specified in request |
selectedCity | object | Completed only | Geographic location used for rendering |
bandwidthMetrics | object | Completed only | Network usage statistics |
captcha | object | Completed only | CAPTCHA detection and handling information |
timingBreakdown | object | Completed only | Performance metrics in milliseconds |
fetchResponses | string | Completed only (if requested) | Base64-encoded, gzipped JSON array of fetch responses |
errorCode | string | Failed only | Machine-readable error code (e.g., RENDER_TIMEOUT). See Error Codes |
errorMessage | string | Failed only | Human-readable error description |
billable | boolean | Yes | Whether this render was billed |
charged | boolean | Yes | Whether a charge was applied to your account balance |
chargedAmountCents | number | Yes | Amount charged in cents (1 for billable, 0 for system errors) |
retryAfter | number | Yes | Server-suggested seconds to wait before next poll |
Selected City Object
{
"name": "new.york",
"displayName": "New York",
"latitude": 40.7128,
"longitude": -74.0060,
"timezoneId": "America/New_York"
}
Bandwidth Metrics Object
{
"networkBytes": 2048576,
"cachedBytes": 512000,
"cacheHitRate": "20.0%"
}
| Field | Type | Description |
|---|---|---|
networkBytes | number | Bytes downloaded from network |
cachedBytes | number | Bytes served from browser cache |
cacheHitRate | string | Percentage of requests served from cache |
CAPTCHA Object
{
"detected": true,
"handled": true,
"sitekey": "6LdABCDEFGHIJKLMNOP"
}
| Field | Type | Description |
|---|---|---|
detected | boolean | Whether a CAPTCHA was detected |
handled | boolean | Whether the CAPTCHA was successfully solved |
sitekey | string | CAPTCHA site key (if detected) |
Timing Breakdown Object
Performance timing breakdown showing milliseconds spent in each phase of the render. Useful for debugging slow renders and optimizing performance.
All times in milliseconds:
{
"browserInitMs": 245,
"navigationMs": 607,
"loadStrategyMs": 156,
"captchaMs": 0,
"waitActionsMs": 0,
"screenshotMs": 0,
"htmlCaptureMs": 89,
"totalMs": 759
}
| Field | Type | Description |
|---|---|---|
browserInitMs | number | Time to initialize the browser instance |
navigationMs | number | Time for page navigation (loading the URL) |
loadStrategyMs | number | Time waiting for load strategy (networkIdle, domContentLoaded, etc.) |
captchaMs | number | Time spent detecting and solving CAPTCHAs |
waitActionsMs | number | Time spent executing user's waitFor actions |
screenshotMs | number | Time to capture user screenshot (0 if not requested) |
htmlCaptureMs | number | Time to extract the final HTML |
totalMs | number | Total render time (sum of all phases) |
Data Retention
Render data is retained for 365 days with the following access patterns:
API Access (24 Hours)
Renders are available via this API endpoint for 24 hours after creation. During this window:
- Retrieval time: <50ms (optimized for real-time workflows)
- Typical usage: Poll for completion, retrieve results, process immediately
This covers the vast majority of web scraping workflows where results are retrieved within minutes or hours of creation.
Dashboard Access (365 Days)
After 24 hours, renders remain accessible via the Browser7 Dashboard for the full 365-day retention period:
- View render details and metadata
- Download HTML, screenshots, and fetch responses
- Export or analyze historical renders
Note: If you need programmatic access to renders older than 24 hours, please contact support to discuss enterprise API options.
Data Decompression
The html and fetchResponses fields are compressed to reduce bandwidth:
- Content is gzipped
- Gzipped data is base64-encoded
- Encoded string is returned in JSON
Decompression Examples
Node.js:
const zlib = require('zlib');
const { promisify } = require('util');
const gunzip = promisify(zlib.gunzip);
// Decompress HTML
const buffer = Buffer.from(result.html, 'base64');
const decompressed = await gunzip(buffer);
const html = decompressed.toString('utf-8');
// Decompress fetchResponses
const fetchBuffer = Buffer.from(result.fetchResponses, 'base64');
const fetchDecompressed = await gunzip(fetchBuffer);
const fetchResponses = JSON.parse(fetchDecompressed.toString('utf-8'));
Python:
import base64
import gzip
import json
# Decompress HTML
html_bytes = base64.b64decode(result['html'])
html = gzip.decompress(html_bytes).decode('utf-8')
# Decompress fetchResponses
fetch_bytes = base64.b64decode(result['fetchResponses'])
fetch_responses = json.loads(gzip.decompress(fetch_bytes).decode('utf-8'))
PHP:
// Decompress HTML
$htmlBytes = base64_decode($result['html']);
$html = gzdecode($htmlBytes);
// Decompress fetchResponses
$fetchBytes = base64_decode($result['fetchResponses']);
$fetchResponses = json_decode(gzdecode($fetchBytes), true);
Note: All Browser7 SDKs handle decompression automatically.
Polling Pattern
Renders are processed asynchronously. Poll this endpoint until the status changes from processing:
- Create render with POST /renders
- Wait 2-3 seconds before first poll
- GET /renders/:id to check status
- If
statusisprocessing, waitretryAfterseconds and repeat step 3 - If
statusiscompleted, process the HTML - If
statusisfailed, handle the error
Polling Best Practices
- Respect
retryAfter- Use the server-suggested interval for optimal performance - Initial delay - Wait 2-3 seconds before first poll (renders rarely complete instantly)
- Timeout - Set a maximum polling time (e.g., 60 seconds)
- Exponential backoff - If implementing custom retry logic, increase intervals gradually
Examples
Basic Request
curl https://api.browser7.com/v1/renders/ren_abc123xyz \
-H "Authorization: Bearer b7_your_api_key"
Polling Loop (Bash)
RENDER_ID="ren_abc123xyz"
# Wait before first poll
sleep 3
# Poll until completed or failed
while true; do
RESPONSE=$(curl -s https://api.browser7.com/v1/renders/$RENDER_ID \
-H "Authorization: Bearer b7_your_api_key")
STATUS=$(echo $RESPONSE | jq -r '.status')
if [ "$STATUS" = "completed" ]; then
echo "Render completed!"
echo $RESPONSE | jq -r '.html' | base64 -d | gunzip
break
elif [ "$STATUS" = "failed" ]; then
echo "Render failed!"
echo $RESPONSE | jq -r '.error'
break
else
echo "Status: $STATUS - waiting..."
sleep 1
fi
done
SDK Examples
The SDKs provide both low-level and high-level methods:
Node.js
const Browser7 = require('browser7');
const client = new Browser7({ apiKey: 'b7_your_api_key' });
// Low-level: Get render status
const result = await client.getRender('ren_abc123xyz');
console.log(result.status); // 'processing' | 'completed' | 'failed'
if (result.status === 'completed') {
console.log(result.html); // Automatically decompressed
}
// High-level: Automatic polling (recommended)
const result = await client.render('https://example.com');
// Returns when completed, html is already decompressed
console.log(result.html);
Python
from browser7 import Browser7
client = Browser7(api_key='b7_your_api_key')
# Low-level: Get render status
result = client.get_render('ren_abc123xyz')
print(result.status) # 'processing' | 'completed' | 'failed'
if result.status == 'completed':
print(result.html) # Automatically decompressed
# High-level: Automatic polling (recommended)
result = client.render('https://example.com')
# Returns when completed, html is already decompressed
print(result.html)
PHP
use Browser7\Browser7Client;
$client = new Browser7Client('b7_your_api_key');
// Low-level: Get render status
$result = $client->getRender('ren_abc123xyz');
echo $result->status; // 'processing' | 'completed' | 'failed'
if ($result->status === 'completed') {
echo $result->html; // Automatically decompressed
}
// High-level: Automatic polling (recommended)
$result = $client->render('https://example.com');
// Returns when completed, html is already decompressed
echo $result->html;
Error Responses
404 Not Found
Returned when the render ID doesn't exist:
{
"error": "Not Found",
"message": "Render not found"
}
Common causes:
- Invalid render ID
- Render ID from a different account
- Typo in the render ID
401 Unauthorized
See Authentication for authentication error details.
Related Documentation
- Create Render - Start a new render job
- Error Handling - Handle API errors
- Rate Limits - Rate limiting details