The MCP server
The same API, spoken over the Model Context Protocol, so an AI client can render a page itself instead of being told how to write the HTTP request. Five tools: one takes a screenshot, one prints a PDF, one reports where the account stands, and two submit and poll a batch. Underneath they are the endpoints the rest of this documentation describes, running the same validation, the same permissions, the same credits and the same cache.
Connecting a client
The server is at https://screenshotbuddy.io/mcp, over streamable HTTP. A client needs two things from you: that URL
and an Authorization header carrying an API token, the same header a REST call sends.
There is no OAuth step and nothing to install.
claude mcp add --transport http screenshotbuddy https://screenshotbuddy.io/mcp --header "Authorization: Bearer <your API key>"
Run it in the project you want the server available in. Claude Code keeps the header with the server, so the token travels on every call and never has to be repeated.
{
"mcpServers": {
"screenshotbuddy": {
"url": "https://screenshotbuddy.io/mcp",
"headers": {
"Authorization": "Bearer <your API key>"
}
}
}
}
Cursor reads .cursor/mcp.json in a project and ~/.cursor/mcp.json everywhere. Any
other client that can add a remote MCP server takes the same two values under whatever it calls them, so if you
can give it a URL and a header you can connect it. The agents page carries
the same setup for a few more clients, and the one for a client that reads Agent Skills rather than MCP servers.
Whatever the client, commit the URL and not the token. The file that names the server is a file people share; the token is a credential that spends your credits.
The five tools
take-screenshot and create-pdf take the parameters their REST counterparts take, from
the same description of the API, and are checked by the same rules: a combination refused over
GET /v1/snap is refused here in the same sentence. There is no
pdf switch to set, because the tool is the mode. That is also what lets each tool publish the exact
range its own mode allows rather than the wider of the two.
-
Name
take-screenshotDescriptionRenders a publicly reachable page and hands the image back in the conversation, so the model can look at what it captured rather than read a description of it. Beside the image comes a line naming the URL, the size and the format, and saying what the render cost. Its parameters are the screenshot options.
-
Name
create-pdfDescriptionPrints a page and answers with a link to the rendering rather than with the file, because a PDF is far too large to travel in a tool result. The page is rendered on the call, so a failure surfaces to the agent that can act on it rather than to whoever clicks the link. Its parameters are the PDF options.
-
Name
check-usageDescriptionAnswers with the document
GET /v1/usageserves, built by the same code: credits remaining, the plan, when the period resets and both per-minute limits. It reports zero rather than refusing when the account has nothing left, which is the case it exists for. See the usage endpoint. -
Name
submit-render-batchDescriptionQueues up to 20 renders in one call and answers immediately with the batch and its id, every item still queued. Nothing renders on the call and nothing is billed by it: each item is rendered in the background and billed as it would have been one at a time. An item takes the same parameters as the two rendering tools, plus
pdfto make it a PDF, under the batch rules. -
Name
check-render-batchDescriptionReports where a submitted batch has got to: the document
GET /v1/renders/{batch}serves, built by the same code, with a signed URL for every finished item and the machine readable reason for every failure. Polling is free the waycheck-usageis free, so poll a few seconds apart until the batch reports itself finished.
The link create-pdf answers with is an ordinary
signed URL, minted for you rather than by you. It needs
no token, so it can be opened or forwarded as it is, and it works for at most 24 hours,
less when the cached copy behind it lapses first. It is signed with the signing secret of the token that called
the tool, which means it carries that token's permissions and stops working the moment that token is
revoked or rotated. Opening it while the copy is still cached is free; a call that turned caching off leaves
nothing to serve, so opening that link renders the page again and costs another credit, and the tool says so.
A refusal comes back as the error a REST caller would have received, carrying the same machine readable
code from the same published set. A model can therefore tell
missing_ability, which no retry fixes, from
render_timeout, which one might, without reading the English
beside it. Every error code.
The token it authenticates with
The same tokens as the REST API, created in the same place: Settings, API tokens. Copy the value while it is on screen and paste it into the header above. There is deliberately no endpoint that mints a token, so an agent cannot create one for itself, and a token that expires or is rotated stops working here at the same moment it stops working everywhere else.
The two permissions narrow the tools
exactly as they narrow the endpoints. A token granted screenshot and not pdf can call
take-screenshot and is refused by create-pdf, with the same
missing_ability the REST call answers
403 with, and the refusal happens before any credit is spent. Narrowing a token before handing it
to an agent is the cheapest way to decide what it may spend your credits on.
A call with no token at all, or with one we do not recognise, never reaches a tool: the endpoint answers
401 and the client reports that it cannot connect.
What it costs
One credit per fresh render, exactly as over HTTP. An identical call repeated is answered from your
cache and costs nothing, and both rendering tools say which
of the two happened in the line beside their answer, so a model can tell a paid render from a free one and has a
reason to reach for the cache. check-usage is free whatever it reports.
The per-minute budgets are counted in the flow both surfaces share, not per surface, so a client gets no second allowance by asking over MCP rather than over HTTP. A fresh render spends the render budget; an answer served from the cache comes out of the separate and far larger cached-answer budget instead. How the two budgets work.
The transport carries a ceiling of its own, set at the sum of those two budgets, and it exists for the calls
that never reach a render at all: the protocol handshake, the tool listing, check-usage. Those cost
a slot here and nothing anywhere else, which is why asking how much is left never spends a render. A client
using the tools as intended meets its render budget long before the ceiling, which is only there to clip a
flood.
When the capture is not the page you asked for
A login wall, a 404 page and a rate limit notice all render perfectly, so the image alone gives a
model no way to tell them from the page it wanted. Over HTTP that is the
X-Target-Status header. Over MCP,
take-screenshot says it in words, at the end of the line that describes the capture, and only when
the target answered something other than a 2xx: a sentence on every successful capture would be
noise a model learns to skip, and the point of this one is that it is unusual.
Nothing about billing moves. The page the server actually served was loaded and rendered, so it costs the credit
any render costs. create-pdf reports no such status, here as over HTTP, so the document itself is
the only thing that says what was captured.
Batches go over the REST endpoint
The tools render one page at a time, which is what a conversation wants. A set of captures, or a page slow
enough to outlast a tool call, is submitted as a batch over the REST endpoint instead:
POST /v1/renders with the same bearer token.
There is no batch tool on this server, so that submission is an HTTP request rather than a tool call.
Batch and async renders.
Settle a capture before an agent spends credits on it
The tools take the parameters the playground sends, so try the awkward ones in the browser and hand the agent the values that worked.