Skillforge Render API
Live today: free trial API keys (100 units, one key per IP per day), the render endpoints (/v1/screenshot, /v1/pdf, /v1/og, /v1/extract, and the matching MCP tools), the MCP tools/list/initialize handshake, and paid top-ups (/v1/topup returns a real Stripe checkout link; credits land on your key automatically after payment).
What it does
One API, four render kinds: a screenshot of a URL or raw HTML, a PDF of a URL or raw HTML, an Open Graph image from HTML you send, or an extraction of a URL into markdown or schema-structured JSON. Credits are prepaid; you buy a pack once and draw it down per render. No monthly plan, no seat count, no expiring subscription to cancel.
Free trial
Create a key with no signup and no card. Each key starts with 100 units. Limited to one key per IP address per day.
curl -X POST https://render.skillforge99.com/v1/keys
Response:
{"apiKey":"sfr_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}
Save that key. It is shown once and is the only credential the API uses; there is no separate account or password.
Endpoints
Every render endpoint takes Authorization: Bearer <your key>. Each call returns two headers on success: x-render-units (units this call cost) and x-credit-remaining (units left on the key).
Screenshot
POST /v1/screenshot · 1 unit, or 2 units with fullPage: true
curl -X POST https://render.skillforge99.com/v1/screenshot \
-H "Authorization: Bearer sfr_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com","width":1280,"height":800,"format":"png"}' \
--output screenshot.png
Give it url or html (not both). Optional: width (320-1920), height (240-1080), fullPage (boolean), format (png, jpeg, or webp).
POST /v1/pdf · 2 units
curl -X POST https://render.skillforge99.com/v1/pdf \
-H "Authorization: Bearer sfr_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com"}' \
--output page.pdf
Give it url or html (not both). Optional: width, height.
Open Graph image
POST /v1/og · 1 unit
curl -X POST https://render.skillforge99.com/v1/og \
-H "Authorization: Bearer sfr_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"html":"<div style=\"font-size:64px\">Hello Skillforge</div>","width":1200,"height":630}' \
--output og.png
Takes html only (no url), capped at 100KB. Optional: width, height.
Extract
POST /v1/extract · 2 units (markdown) or 8 units (structured)
Loads a URL in a real browser (JavaScript runs first), then reads the page back as either clean markdown or JSON matching a schema you send. Deterministic: the same page produces the same output, a field the page doesn't have comes back null, and nothing is guessed or filled in by a model.
Markdown (default mode, 2 units):
curl -X POST https://render.skillforge99.com/v1/extract \
-H "Authorization: Bearer sfr_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com"}'
Response (text/markdown; charset=utf-8):
# Example Domain
This domain is for use in documentation examples...
[Learn more](https://iana.org/domains/example)
Structured (8 units), with a schema of the fields you want back:
curl -X POST https://render.skillforge99.com/v1/extract \
-H "Authorization: Bearer sfr_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com","mode":"structured","schema":{"properties":{"title":{"type":"string"},"description":{"type":"string"}}}}'
Response (application/json):
{
"url": "https://example.com/",
"data": {
"title": "Example Domain",
"description": null
},
"filled": 1,
"total": 2
}
Give it url only (no html). Optional: mode (markdown, default, or structured). structured requires schema: a plain object, up to 8KB, up to 24 properties, each typed string, number, boolean, or array (no nested objects). A field the page has no match for (no meta tag, no JSON-LD, no microdata, no matching heuristic) returns null in data rather than a guess; filled and total tell you how many of the requested fields actually resolved.
All four reject private and internal targets (localhost, 127.0.0.1, RFC1918 ranges, link-local, .internal/.local hosts) with 400 bad_url. Only http and https URLs are accepted.
Connect over MCP
The same four renders are exposed as MCP tools (screenshot_url, render_pdf, render_og, extract_page) at a single streamable-HTTP endpoint. tools/list, initialize, and tools/call all work today; tools/call bills and renders through the same pipeline as the HTTP endpoints above.
curl -X POST https://render.skillforge99.com/mcp \
-H "Authorization: Bearer sfr_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
MCP client config:
{
"mcpServers": {
"skillforge-render": {
"url": "https://render.skillforge99.com/mcp",
"headers": {
"Authorization": "Bearer sfr_YOUR_KEY"
}
}
}
}
Pricing
Every render is 1 unit, except a PDF or a full-page screenshot (2 units), a markdown extract (2 units), or a structured extract (8 units, since it costs more compute to run the page through a schema). Buy a pack once, draw it down, buy another when it runs out.
| Pack | Price | Units |
|---|---|---|
| Starter | $10 | 4,000 |
| Builder | $25 | 11,000 |
| Scale | $50 | 24,000 |
| Render | Cost |
|---|---|
| Screenshot (viewport) | 1 unit |
Screenshot (fullPage: true) | 2 units |
| 2 units | |
| Open Graph image | 1 unit |
| Extract (markdown) | 2 units |
| Extract (structured) | 8 units |
Buying credits
POST /v1/topup with a pack name (p10, p25, or p50) starts a checkout and returns a URL to pay:
curl -X POST https://render.skillforge99.com/v1/topup \
-H "Authorization: Bearer sfr_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"pack":"p25"}'
Open the returned URL to pay. Credits land on your key automatically after payment, no further request needed.
Rate limits
60 requests per minute per key, on top of the credit balance itself. A request over the limit gets 429 rate_limited and does not spend a unit.
FAQ
What happens if a render fails?
You are not charged. If a render throws after a unit was debited, the unit is credited back automatically and the response is a 502 render_failed, not a silent charge.
What about a disputed card charge?
If you dispute a charge, we refund it automatically and disable the key it was used with. We don't fight chargebacks.
Is there a subscription?
No. Packs are one-time purchases. Credits do not expire on a billing cycle because there is no billing cycle.
What do you store?
Nothing beyond short-lived logs (kept up to 24 hours for abuse detection, then deleted). The URLs, HTML, and rendered images or PDFs you send or receive are not retained after the response is returned; there is no dashboard of your past renders because we do not keep the content to show one.
What happens to the pages and data I extract?
The same rule as every other render: nothing beyond short-lived logs (up to 24 hours, abuse detection only, then deleted). The URL you send, the page's HTML, the schema, and the markdown or JSON we hand back are not stored, cached, or reused after the response is returned, and we don't train anything on them. Extraction is also deterministic: we parse the rendered page for what your schema asks for and return null for a field that isn't there. Nothing is inferred or filled in by a model.
Do you resolve hostnames before checking for private IPs?
We block the obvious private and loopback ranges by hostname and literal IP. We do not resolve DNS before that check, so a public hostname that itself points at a private IP is not blocked at this layer (requests still leave from Cloudflare's network, not ours).
What is a "unit"?
The currency your prepaid balance is measured in. A screenshot or Open Graph image is 1 unit; a PDF or a full-page screenshot is 2 units, because those cost more compute to render.
Can an AI agent pay per call without an API key?
Yes. Agent buyers can pay per call in USDC via x402, no account or API key needed: $0.005 for a screenshot, OG image, or markdown extract, $0.01 for a PDF, $0.02 for a structured extract, settled on Base through Coinbase's facilitator.