the whole api, one page.
htmlshare turns an html document into a public url. one endpoint to publish, one mcp server for agents. no sdk, no build step, no account required.
publish in one request.
curl -X POST https://api.htmlshare.net/v1/publish \-H "content-type: application/json" \-d '{"html":"<!doctype html><h1>hello</h1>"}'
response:
{"siteId": "k9m2qa42","url": "https://htmlshare.net/p/k9m2qa42","expiresAt": "2026-08-28T12:00:00.000Z","title": null,"manageToken": "mt_..."}
that's a live page at url. anonymous pages expire after 7 days. keep manageToken if you might want the page later — it's shown once, and signing up lets you claim the site with it (making it permanent).
POST /v1/publish
accepts either application/json with an html string field, or multipart/form-data with a file field (must be text/html or end in .html/.htm). 10 mb max either way.
with an api key you can pass an optional slug (json field or form field) to publish at a memorable url under your claimed prefix:
curl -X POST https://api.htmlshare.net/v1/publish \-H "authorization: Bearer ps_live_..." \-F "file=@report.html" \-F "slug=q3-report"
{"siteId": "x7p4nn21","url": "https://htmlshare.net/@yourprefix/q3-report","expiresAt": null,"title": "Q3 Report"}
slugs are lowercase alphanumeric plus hyphens, 2–64 chars, unique per account. republishing an existing slug returns 409 conflict. authenticated sites never expire (expiresAt is null) and serve at htmlshare.net/@{prefix}/{slug}; anonymous sites serve at htmlshare.net/p/{siteId}.
bearer keys, ps_live_ prefix.
create keys in the dashboard under api keys. each key is shown once at creation. send it as authorization: Bearer ps_live_... on publish requests — uploads are tied to your account, never expire, and get the higher rate limit. an invalid key is a hard 401, not an anonymous fallback. the key works on POST /v1/publish and the mcp connector; managing sites (list, delete) is via the dashboard.
publish from claude or chatgpt.
htmlshare hosts a remote mcp server (streamable http) at https://api.htmlshare.net/v1/mcp. connect it and ask your agent to “publish this as an htmlshare link”. without an api key, connector publishes are anonymous — pages expire in 7 days, and the tool result includes a manageToken, your proof of ownership if you later want to claim the page into an account. add an api key as an authorization header and publishes are permanent, tied to your account, listed in your dashboard, and counted against your own rate limit (30 per 24 hours) instead of the shared connector ip. or skip keys entirely: the server supports oauth sign-in, so the first time a tool call needs your account — a custom slug, editing a page you own — clients that support it (claude.ai does) show a connect prompt. sign in with your email, approve, and you’re publishing as yourself with nothing to paste or store.
tools
publish_html publishes a new page and returns its siteId. to change a page, the agent should read it once with get_html — which returns a trimmed view by default, with script and style bodies and inline images collapsed to size markers, or just the elements matching a css selector — and then send only the changed strings with patch_html. each edit is an exact, unique string replacement, applied all-or-nothing, and the response is the new size rather than the document, so a one-line change costs a few dozen tokens instead of two copies of the page. update_html is for full rewrites only. put_asset stores an image, font, css or js file under the page and returns a stable url to reference instead of a data: uri; publishes that inline images over 4KB get this done automatically. documents over 500KB are rejected rather than truncated. set_slug renames a page to htmlshare.net/@{your-prefix}/{slug} — with an api key, no dashboard visit — or clears it; there are no redirects, so the old url stops working. delete_site is a permanent takedown.
claude.ai
settings → connectors → add custom connector → name it htmlshare, url https://api.htmlshare.net/v1/mcp, and set authentication to required when the server asks (the dialog detects none because anonymous publishing works — this option keeps that and adds sign-in). for the oauth client, choose no client id — register one automatically. that’s the whole setup: publishes start anonymous, and when a tool call needs your account claude shows a connect card — sign in with your email and approve, no api key involved. prefer a key anyway? choose none and add a request header: name Authorization, value Bearer ps_live_... (pasting just the key without the Bearer prefix works too).
claude code
claude mcp add --transport http htmlshare https://api.htmlshare.net/v1/mcp
claude desktop
{"mcpServers": {"htmlshare": {"url": "https://api.htmlshare.net/v1/mcp"}}}
chatgpt
in the chatgpt desktop app: plugins → MCPs → connect to a custom MCP. name it htmlshare, switch type from STDIO to Streamable HTTP (this swaps the command field for a url field), url https://api.htmlshare.net/v1/mcp. to publish under your account, add a header: name Authorization, value Bearer ps_live_... (or use the bearer token env var field, which takes the name of a local env var holding the key). on the web, enable developer mode first (settings → security and login) and add the same url as a custom connection from the plugins page. then enable it from the tools menu in a new chat.
one error shape everywhere.
{"error": {"code": "too_large","message": "File exceeds 10485760 bytes"}}
codes you'll see: bad_request and missing_file (400), invalid_type (400, not html), unauthorized (401), conflict (409, slug taken), too_large (413, over 10 mb), rate_limited (429, with a retryAfter field and Retry-After header).
limits: anonymous publishes are 5 per 24 hours per ip and expire after 7 days. authenticated publishes are 30 per 24 hours and never expire. uploads are scanned for phishing and malware; we never modify your html.