Get Started With UpRender
Everything you need to ship crawler-ready HTML in minutes — set up, plug in your stack, and start serving bots a fully-rendered page.
1. Quick Start
Five minutes from sign-up to serving crawler-ready HTML.
Create an account & add your domain
Sign up at uprender.io, then add your website in the Domain Manager.
Copy your two access keys
Open Domain Manager → Access Credentials to get a User Key and a Domain Key. Both are required on every request.
Install one integration
Pick the integration that matches your stack — Cloudflare Workers, Next.js, Vercel, Express, Nginx, or Nuxt — and drop in the snippet from §3.
Verify with a test request
Hit the cache endpoint with a bot user-agent and confirm you get back rendered HTML.
Test it with cURL
curl -i \ -H "User-Agent: Googlebot" \ -H "X-UpRender-User-Key: YOUR_USER_KEY" \ -H "X-UpRender-Domain-Key: YOUR_DOMAIN_KEY" \ "https://api.uprender.io/api/v1/cache/get?url=https://your-website.com/"
A successful response looks like:
{ "success": true, "html": "<!doctype html>...fully rendered HTML...", "device_type": "desktop", "cached_at": "2026-05-21T08:14:22Z"
}2. How It Works
UpRender sits between your origin and bot traffic. Real users hit your site as usual. Bots — Googlebot, Bingbot, GPTBot, ClaudeBot, and friends — get a fully-rendered HTML snapshot from us instead of your raw JS bundle.
1. Bot arrives
Your edge layer (Cloudflare Worker, Next.js middleware, Nginx, etc.) checks the User-Agent.
2. Route the bot
If it's a bot, the request is forwarded to UpRender with your two access keys.
3. Serve the cache
UpRender returns the latest rendered HTML — or renders it on the fly if there's no cache yet.
4. Humans pass through
Anything that isn't a bot gets your original site, untouched.
Desktop and mobile variants
Plans with mobile rendering enabled render every page twice — once on a 1920×1080 desktop viewport and once on a 412×915 mobile viewport. UpRender automatically returns the matching variant based on the bot's User-Agent.
3. Integration Guides
Pick the guide that matches your stack. Every snippet is self-contained, under 50 lines, and ready to paste in.
3.1 Cloudflare Workers (recommended)
The fastest way to get started — runs at Cloudflare's edge, no server changes required.
const UPRENDER_API = 'https://api.uprender.io/api/v1/cache/get';
const BOT_REGEX = /(googlebot|google-inspectiontool|google-extended|googleother|bingbot|bingpreview|gptbot|chatgpt-user|oai-searchbot|claudebot|claude-user|claude-searchbot|applebot|meta-externalagent|meta-externalfetcher|facebookexternalhit|slackbot|twitterbot|linkedinbot|facebot)/i; export default { async fetch(request, env) { const ua = request.headers.get('User-Agent') || ''; // Real user → straight to origin if (!BOT_REGEX.test(ua)) return fetch(request); // Bot → fetch the rendered HTML from UpRender const upstream = await fetch(`${UPRENDER_API}?url=${encodeURIComponent(request.url)}`, { headers: { 'X-UpRender-User-Key': env.UPRENDER_USER_KEY, 'X-UpRender-Domain-Key': env.UPRENDER_DOMAIN_KEY, 'User-Agent': ua, }, }); if (!upstream.ok) return fetch(request); // fall back to origin on error const { html } = await upstream.json(); return new Response(html, { headers: { 'Content-Type': 'text/html; charset=utf-8' }, }); },
};Add your keys as encrypted secrets:
wrangler secret put UPRENDER_USER_KEY wrangler secret put UPRENDER_DOMAIN_KEY
Finally, attach the Worker to your domain via a Cloudflare Worker Route (e.g. *yourdomain.com/*).
3.2 Next.js (App or Pages Router)
import { NextRequest, NextResponse } from 'next/server'; const BOT_REGEX = /(googlebot|google-inspectiontool|google-extended|googleother|bingbot|bingpreview|gptbot|chatgpt-user|oai-searchbot|claudebot|claude-user|claude-searchbot|applebot|meta-externalagent|meta-externalfetcher|facebookexternalhit|slackbot|twitterbot|linkedinbot)/i; export async function middleware(req: NextRequest) { const ua = req.headers.get('user-agent') || ''; if (!BOT_REGEX.test(ua)) return NextResponse.next(); const resp = await fetch( `https://api.uprender.io/api/v1/cache/get?url=${encodeURIComponent(req.nextUrl.href)}`, { headers: { 'X-UpRender-User-Key': process.env.UPRENDER_USER_KEY!, 'X-UpRender-Domain-Key': process.env.UPRENDER_DOMAIN_KEY!, 'User-Agent': ua, }, } ); if (!resp.ok) return NextResponse.next(); const { html } = await resp.json(); return new NextResponse(html, { headers: { 'Content-Type': 'text/html; charset=utf-8' }, });
} export const config = { matcher: '/((?!_next|api|favicon.ico).*)' };UPRENDER_USER_KEY=your_user_key UPRENDER_DOMAIN_KEY=your_domain_key
3.3 Vercel Edge Functions
Use this for non-Next.js SPAs deployed on Vercel.
export const config = { runtime: 'edge' }; const BOT_REGEX = /(googlebot|google-inspectiontool|google-extended|googleother|bingbot|bingpreview|gptbot|chatgpt-user|oai-searchbot|claudebot|claude-user|claude-searchbot|applebot|meta-externalagent|meta-externalfetcher)/i; export default async function handler(req: Request) { const ua = req.headers.get('user-agent') || ''; if (!BOT_REGEX.test(ua)) return fetch(req); const resp = await fetch( `https://api.uprender.io/api/v1/cache/get?url=${encodeURIComponent(req.url)}`, { headers: { 'X-UpRender-User-Key': process.env.UPRENDER_USER_KEY!, 'X-UpRender-Domain-Key': process.env.UPRENDER_DOMAIN_KEY!, }, } ); const { html } = await resp.json(); return new Response(html, { headers: { 'Content-Type': 'text/html' } });
}{ "rewrites": [{ "source": "/(.*)", "destination": "/api/bot-render" }]
}3.4 Express (Node.js)
const BOT_REGEX = /(googlebot|google-inspectiontool|google-extended|googleother|bingbot|bingpreview|gptbot|chatgpt-user|oai-searchbot|claudebot|claude-user|claude-searchbot|applebot|meta-externalagent|meta-externalfetcher)/i; module.exports = function uprenderMiddleware() { return async (req, res, next) => { if (!BOT_REGEX.test(req.headers['user-agent'] || '')) return next(); try { const url = `${req.protocol}://${req.get('host')}${req.originalUrl}`; const resp = await fetch( `https://api.uprender.io/api/v1/cache/get?url=${encodeURIComponent(url)}`, { headers: { 'X-UpRender-User-Key': process.env.UPRENDER_USER_KEY, 'X-UpRender-Domain-Key': process.env.UPRENDER_DOMAIN_KEY, 'User-Agent': req.headers['user-agent'], }, } ); if (!resp.ok) return next(); const { html } = await resp.json(); res.set('Content-Type', 'text/html; charset=utf-8').send(html); } catch { next(); } };
};const express = require('express');
const uprender = require('./uprender-middleware'); const app = express();
app.use(uprender());
// ... your routes
app.listen(3000);3.5 Nginx reverse proxy
map $http_user_agent $is_bot { default 0; "~*(googlebot|google-inspectiontool|google-extended|googleother|bingbot|bingpreview|gptbot|chatgpt-user|oai-searchbot|claudebot|claude-user|claude-searchbot|applebot|meta-externalagent|meta-externalfetcher)" 1;
} server { listen 80; server_name yourdomain.com; location / { if ($is_bot) { proxy_pass https://api.uprender.io/api/v1/cache/get?url=$scheme://$host$request_uri; } proxy_set_header X-UpRender-User-Key "$UPRENDER_USER_KEY"; proxy_set_header X-UpRender-Domain-Key "$UPRENDER_DOMAIN_KEY"; proxy_pass http://localhost:3000; # origin fallback }
}set directives or a sidecar template.3.6 Vue / Nuxt 3
export default defineEventHandler(async (event) => { const ua = getHeader(event, 'user-agent') || ''; if (!/(googlebot|bingbot|gptbot|claudebot)/i.test(ua)) return; const url = getRequestURL(event).href; const resp = await $fetch<{ html: string }>( `https://api.uprender.io/api/v1/cache/get?url=${encodeURIComponent(url)}`, { headers: { 'X-UpRender-User-Key': process.env.UPRENDER_USER_KEY!, 'X-UpRender-Domain-Key': process.env.UPRENDER_DOMAIN_KEY!, }, } ); setHeader(event, 'Content-Type', 'text/html; charset=utf-8'); return resp.html;
});4. Cache API
These are the endpoints your edge integration calls. All requests need the two access-key headers.
Authentication
X-UpRender-User-Key: <your user access key> X-UpRender-Domain-Key: <your domain access key>
Find both keys in Domain Manager → Access Credentials. Rotate either one any time — old keys stop working immediately.
Get cached HTML
GET https://api.uprender.io/api/v1/cache/get?url=<full-url> X-UpRender-User-Key: <user key> X-UpRender-Domain-Key: <domain key>
Response:
{ "success": true, "html": "<!doctype html>...", "device_type": "desktop", "cached_at": "2026-05-21T08:14:22Z"
}Re-render a URL
Trigger a fresh render — useful after publishing new content. Requires a logged-in dashboard session (Bearer token).
POST https://api.uprender.io/api/v1/cache/refresh
Authorization: Bearer <your dashboard JWT>
Content-Type: application/json { "url": "https://yourdomain.com/blog/new-post" }Clear by pattern
Invalidate every URL matching a pattern. Handy after a site-wide redesign.
POST https://api.uprender.io/api/v1/cache/clear
Authorization: Bearer <your dashboard JWT>
Content-Type: application/json { "pattern": "https://yourdomain.com/blog/*" }5. Configuration
Every option below is controllable from the dashboard — no code changes needed.
Domain settings
Mobile rendering
Render every page on both desktop and mobile viewports. Available on Starter and above.
llms.txt
Auto-publish a /llms.txt file listing your URLs for AI crawlers. Enabled by default.
AI visibility
Run LLM analysis on every render to score AEO/GEO and surface fixes in AI Audit Studio.
Tracked Bots
View AI, search, social, and other crawler traffic with trends, verification status, and recent requests.
Sitemap management
Sitemaps drive which URLs UpRender renders. You have four ways to get one in:
- Auto-discover — UpRender scans
robots.txt, your homepage, and 15 common paths. - Submit a URL — paste your sitemap URL directly.
- Upload a file — drop in a
.xmlor.xml.gzsitemap. - Paste a URL list — one URL per line; we'll build a synthetic sitemap.
If none of those produce a sitemap, UpRender will generate one for you from URLs discovered during your first crawl.
Refreshing content after a deploy
Three options depending on how much you changed:
- Single page — click Re-render on the URL row in Cache Manager.
- Pattern — Cache Manager → Clear by pattern → enter
/blog/*. - Everything — Cache Manager → Re-render all. Runs in the background; track progress in the activity log.
6. Plans & Add-ons
Pick a plan that fits your traffic. If you spike, top up with add-ons instead of upgrading.
Free
1 domain · 500 renders/mo · No mobile rendering
Starter
3 domains · 10 000 renders/mo · Mobile + AI visibility
Pro
10 domains · 100 000 renders/mo · Everything in Starter
Enterprise
Unlimited domains · negotiated quotas · SLA + support
Add-ons
Top-ups that stay valid until consumed — they never expire monthly.
- URL Packs — extra render quota (10k, 50k, 100k, or custom).
- AI Credit Packs — extra AI credits for AI visibility and audits.
Buy them from Dashboard → Billing → Add-ons. Quota lifts within seconds of payment.
Invoices & receipts
Every payment generates an invoice and a receipt, both downloadable as PDFs from Billing → Transaction History. To include a GST or VAT number, fill in your tax ID under Settings → Billing Address before your next payment.
Go to Billing7. FAQ
How does UpRender know which requests are bots?
We match the User-Agent against a curated list of known crawlers (Googlebot, Bingbot, GPTBot, ClaudeBot, Slackbot, etc.) plus header heuristics, then show the traffic in Tracked Bots.
Will my human visitors notice anything?
No. Your edge integration only routes bot traffic to UpRender — everyone else hits your origin exactly as before.
How are renders counted against my quota?
Each unique combination of (URL, device) renders against your monthly quota. Cache hits don't count. Re-renders triggered by a purge or sitemap update do.
Can I upgrade in the middle of a billing period?
Yes — you'll be prorated. Downgrades take effect at the next renewal.
My renders look incomplete — what should I check?
Make sure your page finishes loading within the render timeout (Settings → Rendering). Check the Render Detail panel for console errors. Cookies and auth headers are stripped by design, so anything behind login won't render.
How do I purge the cache when I publish new content?
Call POST /api/v1/cache/refresh from your CMS publish hook, or use the Re-render button on the URL row in Cache Manager.
Where do I find my invoice?
Dashboard → Billing → Transaction History. Each row has a Download Invoice button.
Can I add a GST or VAT ID to my invoices?
Yes — Settings → Billing Address has a Tax ID field. Anything paid after you save it includes the ID on the invoice.
8. Support
We're here when you need us. Most questions are answered within one business day.
Response time: within one business day (Mon–Fri, IST). For urgent production issues on Pro or Enterprise plans, mark your email subject with [URGENT].