AppFrame exposes a free, read-only JSON API and a Model Context Protocol (MCP) server. Use them to look up an iOS app on the App Store and get the AppFrame editor link where a launch image can be created, to list the available themes, fonts and formats, or to read pricing and blog content. Image rendering happens in the browser editor and is not available through the API.
https://appfra.mehttps://appfra.me/mcp · server cardNone. All endpoints are public and read-only. CORS is open.
GET /api/v1/infoSite info, how it works, Free and Pro plans, contact and links.
GET /api/v1/themesThe 20 themes (dark, light, bold; free or Pro), 9 fonts and 6 social formats.
GET /api/v1/apps?q={name|id|url}&country={cc}Look up App Store apps with the AppFrame editor URL. App Store ID or URL is reliable; name search is best-effort and can return 502 upstream_error.
GET /api/v1/blogAll blog posts with title, description, date and URL.
GET /api/v1/healthHealth check.
curl -s "https://appfra.me/api/v1/apps?q=1232780281&country=us" curl -s https://appfra.me/api/v1/themes curl -s https://appfra.me/ -H "Accept: text/markdown"
Streamable HTTP transport, JSON-RPC 2.0 over POST, no session required. Tools: get_appframe_info, list_themes, search_apps, list_blog_posts. Resources: appframe://info, appframe://themes, https://appfra.me/llms.txt.
curl -s https://appfra.me/mcp -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"search_apps","arguments":{"q":"https://apps.apple.com/app/id1232780281"}}}'Client config (Claude Desktop, Cursor and others that support remote MCP):
{ "mcpServers": { "appframe": { "url": "https://appfra.me/mcp" } } }60 requests per minute per IP across /api/v1/* and /mcp. Every response carries the IETF headers RateLimit-Policy: "default";q=60;w=60 and RateLimit: "default";r=<remaining>;t=<seconds>. Over the limit you get HTTP 429 with Retry-After.
Errors use RFC 9457 application/problem+json with type, title, status, detail, code and resolution. Codes:
invalid_query (400): missing or too long q.invalid_country (400): country is not a 2-letter code.not_found (404): no matching app, or unknown endpoint.method_not_allowed (405): /mcp accepts only POST (and OPTIONS).rate_limited (429): wait for the reset, then retry.upstream_error (502): the App Store search did not respond; retry.error (500): any other failure; the status field carries the real HTTP status.{
"type": "https://appfra.me/docs#error-invalid_query",
"title": "Invalid query",
"status": 400,
"detail": "Parameter 'q' is required (1-100 characters).",
"code": "invalid_query",
"resolution": "Pass an app name, a numeric App Store ID or an App Store URL in 'q'."
}/api/v1 is stable. Fields may be added; existing fields are not removed or renamed./api/v2), and v1 keeps running alongside it.Deprecation (RFC 9745) and Sunset (RFC 8594) response headers, plus Link: <https://appfra.me/docs#versioning>; rel="deprecation".No package to install: the API works with curl and jq.
# Free themes curl -s https://appfra.me/api/v1/themes | jq -r '.themes[] | select(.free) | .name' # Editor URL for an App Store app curl -s "https://appfra.me/api/v1/apps?q=https://apps.apple.com/app/id1232780281" | jq -r '.results[0].editorUrl' # Latest blog posts curl -s https://appfra.me/api/v1/blog | jq -r '.posts[:5][] | "(.date) (.title)"' # Pro price curl -s https://appfra.me/api/v1/info | jq '.plans[] | select(.id=="pro") | .price'
Every page is also available as Markdown: send Accept: text/markdown to any URL, or append ?format=md.