JavaScript rendering enables full browser execution to capture dynamically loaded content, handle user interactions, and process JavaScript-heavy websites. Control rendering behavior with advanced options for timeout, iframe handling, and load detection.
When to use
Use JavaScript rendering when you need to:
- Load dynamic content: Capture content loaded via AJAX or fetch requests
- Execute JavaScript: Process sites that require JS for content display
- Handle SPAs: Extract data from Single Page Applications (React, Vue, Angular)
- Wait for interactions: Capture DOM state after user actions
- See final state: Get the page as users see it, not raw HTML
Rendering requires vx8, vx10, or vx14 drivers. The vx6 driver does not support rendering.
Supported parameters
Available in - Extract
| Parameter | Type | Description | Default |
|---|
render | Boolean | Enable or disable JS rendering | false |
render_options | Object | Max wait time in milliseconds | - |
Render options parameter
The render_options parameter provides fine-grained control over rendering behavior:
| Parameter | Type | Description | Default |
|---|
render_type | String | When to consider page “loaded”, refer to render types below to see available options | load |
timeout | Integer | Max wait time in milliseconds | 30000 |
include_iframes | Boolean | Whether to load iframe content | false |
blocked_domains | Array | Domains to block from loading | [] |
Render types
Control when the page is considered fully loaded:
| Type | Description | Use Case |
|---|
load | Wait for standard load event | Default for most pages |
domready | Wait for DOMContentLoaded event | Faster, before all resources load |
idle2 | Wait for ≤2 network connections in last 500ms | Dynamic content still loading |
idle0 | Wait for 0 network connections in last 500ms | Ensure everything is loaded |
Usage
Enable basic rendering
Set render: true to enable JavaScript execution:
from nimble import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.extract({
"url": "https://www.example.com",
"render": True
})
print(result)
When render: false (default), the API returns the raw HTML without JavaScript execution, suitable for static pages.
Advanced JS rendering
from nimble import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
result = nimble.extract({
"url": "https://www.example.com",
"render": True,
"render_options": {
"render_type": "idle0",
"timeout": 60000,
"include_iframes": True,
"blocked_domains": ["ads.example.com", "tracking.example.com"]
}
})
print(result)
Dynamic content loading
Wait for AJAX-loaded content:
from nimble import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Wait for all network activity to stop
result = nimble.extract({
"url": "https://www.example.com/products",
"render": True,
"render_options": {
"render_type": "idle0",
"timeout": 45000
}
})
print(result["data"]["html"])
Single Page Applications
Extract from React, Vue, or Angular apps:
from nimble import Nimble
from pydantic import BaseModel
class Product(BaseModel):
name: str
price: float
rating: float
nimble = Nimble(api_key="YOUR-API-KEY")
# SPAs need rendering and proper wait time
result = nimble.extract({
"url": "https://spa-example.com/products",
"render": True,
"render_options": {
"render_type": "idle2",
"timeout": 30000
},
"schema": Product
})
print(result["data"])
Include iframe content in extraction:
from nimble import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Include iframe content (e.g., embedded videos, widgets)
result = nimble.extract({
"url": "https://www.example.com/page-with-iframes",
"render": True,
"render_options": {
"include_iframes": True,
"render_type": "load",
"timeout": 40000
},
"formats": ["html"]
})
print(result["data"]["html"])
Block unnecessary resources
Improve performance by blocking ads and tracking:
from nimble import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Block ads, analytics, and tracking domains
result = nimble.extract({
"url": "https://www.example.com",
"render": True,
"render_options": {
"blocked_domains": [
"googletagmanager.com",
"google-analytics.com",
"facebook.com",
"doubleclick.net",
"ads.example.com"
],
"render_type": "idle2",
"timeout": 25000
}
})
print(result)
Fast rendering for simple sites
Use DOMContentLoaded for faster responses:
from nimble import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Don't wait for images/styles to load
result = nimble.extract({
"url": "https://www.example.com/article",
"render": True,
"render_options": {
"render_type": "domready",
"timeout": 15000
},
"formats": ["markdown"]
})
print(result["data"]["markdown"])
Combining with browser actions
Rendering works seamlessly with browser actions:
from nimble import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Render page, then perform actions
result = nimble.extract({
"url": "https://www.example.com",
"render": True,
"render_options": {
"render_type": "idle0",
"timeout": 30000
},
"browser_actions": [
{
"wait_and_click": {
"selector": "button.load-more",
"timeout": 5000
}
},
{
"wait": {
"delay": 2000
}
},
{
"infinite_scroll": {
"duration": 5000
}
}
]
})
print(result)
Best practices
Choose the right render type
Use load for standard pages:
# ✅ Default for most websites
render_options = {
"render_type": "load"
}
Use domready for speed:
# ✅ When images/styles aren't needed
render_options = {
"render_type": "domready" # Faster response
}
Use idle2 for dynamic content:
# ✅ For AJAX-heavy pages
render_options = {
"render_type": "idle2", # Wait for most requests to finish
"timeout": 30000
}
Use idle0 for complete loading:
# ✅ When you need everything loaded
render_options = {
"render_type": "idle0", # Wait for all network activity
"timeout": 60000 # Higher timeout for slow sites
}
Optimize timeout settings
Set appropriate timeouts:
# ❌ Too short - may miss content
render_options = {
"render_type": "idle0",
"timeout": 5000 # Not enough for slow sites
}
# ✅ Balanced timeout
render_options = {
"render_type": "idle0",
"timeout": 30000 # 30 seconds is usually sufficient
}
# ✅ Extended for slow sites
render_options = {
"render_type": "idle0",
"timeout": 60000 # Up to 60 seconds for very slow sites
}
Block unnecessary domains
Common domains to block:
common_blocked_domains = [
# Analytics
"google-analytics.com",
"googletagmanager.com",
"segment.com",
"mixpanel.com",
# Advertising
"doubleclick.net",
"googlesyndication.com",
"adservice.google.com",
# Social media widgets
"facebook.com",
"twitter.com",
"linkedin.com",
# CDN for ads
"ads.example.com",
"tracking.example.com"
]
result = nimble.extract({
"url": "https://www.example.com",
"render": True,
"render_options": {
"blocked_domains": common_blocked_domains
}
})
Benefits of blocking:
- Faster page loads
- Lower bandwidth usage
- Reduced detection risk
- Cleaner HTML output
Handle iframes carefully
Enable only when needed:
# ❌ Don't enable iframes unnecessarily
render_options = {
"include_iframes": True # Slower and larger response
}
# ✅ Enable only for specific content
if need_iframe_content:
render_options = {
"include_iframes": True,
"timeout": 45000 # Increase timeout for iframes
}
else:
render_options = {
"include_iframes": False
}
Combine with network capture
Monitor and capture API calls during rendering:
from nimble import Nimble
nimble = Nimble(api_key="YOUR-API-KEY")
# Render page and capture specific API calls
result = nimble.extract({
"url": "https://www.example.com",
"render": True,
"render_options": {
"render_type": "idle0",
"timeout": 30000
},
"network_capture": [
{
"method": "GET",
"url": {
"type": "contains",
"value": "/api/products"
}
}
]
})
# Access captured network data
api_responses = result["data"]["network_capture"]
print(api_responses)
Choose the minimal driver:
# ❌ Don't use vx10 when vx8 works
result = nimble.extract({
"url": "https://simple-spa.com",
"driver": "vx10", # Unnecessary stealth features
"render": True
})
# ✅ Use appropriate driver
result = nimble.extract({
"url": "https://simple-spa.com",
"driver": "vx8", # Sufficient for most SPAs
"render": True
})
Monitor execution time:
result = nimble.extract({
"url": "https://www.example.com",
"render": True
})
# Check rendering performance
exec_time = result["metadata"]["execution_time_ms"]
print(f"Rendering took {exec_time}ms")
# Optimize if too slow
if exec_time > 10000:
print("Consider blocking domains or changing render_type")
When to skip rendering
Use non-rendering (vx6) when:
- Static content: HTML already contains all data
- API endpoints: Fetching JSON directly
- High throughput needed: Rendering is slower
- Simple pages: No JavaScript required
- Cost optimization: Non-rendering is cheaper
# ✅ Skip rendering for static pages
result = nimble.extract({
"url": "https://static-site.com/page.html",
"render": False, # or omit (false is default)
})