/api/prerender/renderRender a JavaScript page into static HTML. Returns rendered HTML (200) or a passthrough instruction (304 + Location) when prerendering does not apply.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
urlrequired |
string | URL-encoded target page to render. Must be a valid URL. |
cache_invalidate |
string | Set to `1` to skip the cache and force a fresh render. The response is the newly rendered HTML (cache status `miss`) and the stored snapshot is replaced, so later requests serve the updated version. Pass it as a top-level parameter alongside `url`, not inside the encoded `url` value. |
Response Headers
| Header | Values | Description |
|---|---|---|
x-lovablehtml-render-cache |
edge-hit | hit | miss |
Which cache tier served the response (see below) |
x-lovablehtml-snapshot-key |
string | Identifier for the stored HTML snapshot (present on hit) |
cache-control |
public, max-age=N, s-maxage=N |
Cache TTL based on your domain's configured refresh interval |
etag |
W/"sha256" |
Weak etag derived from the HTML content hash |
Cache tiers
edge-hit— served from a short-lived edge tier close to the requester. Lowest latency. May serve stale content for up to 5 minutes after an invalidation.hit— served from the durable snapshot cache. Reflects the latest successful render for your domain's refresh interval.miss— no cache entry was usable; the page was rendered on demand.
cache_invalidate=1 must be its own query parameter, next to url — not inside it. Folded into the encoded url value it becomes part of the target address and is silently ignored (the page stays cached):
- ✅
…/render?url=https%3A%2F%2Fyour-app.com%2Fpage&cache_invalidate=1 - ❌
…/render?url=https%3A%2F%2Fyour-app.com%2Fpage%3Fcache_invalidate%3D1
When set, it skips every cache tier and renders the page from scratch — the new HTML is returned (cache status miss) and saved as the page's snapshot, so later requests serve the updated version. Each forced render is slower than a cached response and counts toward your render usage, so use it to refresh a specific page on demand, not on every request. It renders even when on-demand rendering is turned off for the domain.
To refresh pages without fetching them — in bulk, or after a deploy — use the Cache Invalidation API instead.
Response Body
On 200, returns the fully-rendered HTML string with Content-Type: text/html; charset=utf-8.
On 304, the body is empty. Follow the Location header to the origin URL.
Response Codes
Content-Type: text/htmlLocation header contains origin URL.domain_not_owned or api_key_domain_scope_mismatch.Example
const response = await fetch('https://encited.com/api/prerender/render?url=' +encodeURIComponent('https://your-app.com/page'),{headers: {'x-lovablehtml-api-key': '<API_KEY>','Accept': 'text/html'}});const html = await response.text();// Check response headersconst cacheStatus = response.headers.get('x-lovablehtml-render-cache');// → "edge-hit" or "hit" (cached) or "miss" (fresh render)const snapshotKey = response.headers.get('x-lovablehtml-snapshot-key');// Useful for debugging: the stored HTML object key (when available)
curl -X GET \"https://encited.com/api/prerender/render?url=https%3A%2F%2Fyour-app.com%2Fpage" \-H "x-lovablehtml-api-key: <API_KEY>" \-H "Accept: text/html"# Force a fresh render and replace the stored snapshotcurl -X GET \"https://encited.com/api/prerender/render?url=https%3A%2F%2Fyour-app.com%2Fpage&cache_invalidate=1" \-H "x-lovablehtml-api-key: <API_KEY>" \-H "Accept: text/html"
import requestsimport urllib.parseurl = urllib.parse.quote('https://your-app.com/page', safe='')response = requests.get(f'https://encited.com/api/prerender/render?url={url}',headers={'x-lovablehtml-api-key': '<API_KEY>','Accept': 'text/html'})html = response.textcache_status = response.headers.get('x-lovablehtml-render-cache')
Tip: Static assets (CSS, JS, images, fonts) are never prerendered. Follow the Location header or fetch directly from origin.
