Starhold Render

POST /v1/og

Docs · OG · PDF · Screenshot · Signed URLs · Errors · Limits

Examples

Exactly one of template or html is required.

curl
curl -X POST https://render.starhold.app/v1/og \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"template":"basic","params":{"title":"Hello from Starhold","subtitle":"Made with one API call"}}' \
  -o og.png
JavaScript (fetch)
import { writeFile } from "node:fs/promises";

const res = await fetch("https://render.starhold.app/v1/og", {
  method: "POST",
  headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" },
  body: '{"template":"basic","params":{"title":"Hello from Starhold","subtitle":"Made with one API call"}}',
});
if (!res.ok) throw new Error((await res.json()).error.message);
await writeFile("og.png", Buffer.from(await res.arrayBuffer()));
Python (requests)
import requests

body = '{"template":"basic","params":{"title":"Hello from Starhold","subtitle":"Made with one API call"}}'
res = requests.post("https://render.starhold.app/v1/og",
    headers={"Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json"},
    data=body.encode(), timeout=35)
res.raise_for_status()
open("og.png", "wb").write(res.content)
PHP (curl ext)
<?php
$body = '{"template":"basic","params":{"title":"Hello from Starhold","subtitle":"Made with one API call"}}';
$ch = curl_init("https://render.starhold.app/v1/og");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $body,
    CURLOPT_HTTPHEADER => ["Authorization: Bearer YOUR_API_KEY", "Content-Type: application/json"],
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 35,
]);
$out = curl_exec($ch);
if (curl_getinfo($ch, CURLINFO_HTTP_CODE) !== 200) { die($out); }
file_put_contents("og.png", $out);
Go (net/http)
package main

import (
	"io"
	"net/http"
	"os"
	"strings"
	"time"
)

func main() {
	body := `{"template":"basic","params":{"title":"Hello from Starhold","subtitle":"Made with one API call"}}`
	req, _ := http.NewRequest("POST", "https://render.starhold.app/v1/og", strings.NewReader(body))
	req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
	req.Header.Set("Content-Type", "application/json")
	res, err := (&http.Client{Timeout: 35 * time.Second}).Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	if res.StatusCode != 200 {
		io.Copy(os.Stderr, res.Body)
		os.Exit(1)
	}
	out, _ := os.Create("og.png")
	io.Copy(out, res.Body)
}

Fields

FieldType and rangeDefault
templatebasic, article, product or docsnone
paramsobject, checked per template (see templates){}
html, cssstrings; html up to 256 KB, css up to 64 KB; css needs htmlnone
width, height200 to 24001200 by 630
formatpng, jpeg or webppng
quality1 to 100 (jpeg and webp)90
cache_ttl0 to 86,400 seconds; 0 turns the cache off for this request86,400

Built-in templates run without JavaScript. Your own html runs with JavaScript on, and cannot reach private addresses.

Template parameters

TemplateParameters (longest allowed)
basictitle (120), subtitle (200), brand (40), theme (light or dark), accent (hex)
articletitle (140), author (60), date (30), site (60), avatar_url (https), accent
productname (60), tagline (140), price (20), image_url (https), accent
docstitle (120), section (40), logo_url (https), accent

For a meta tag

Use a signed URL so you do not have to hand a key to a browser or a crawler.