Caching
Ask for the same page twice and the second answer is the rendering we already made for you. It arrives faster and costs no credit. This page explains when that happens, how to tell that it did, and how to turn it off.
cache=0 so
every request renders the page as it is now.
How it works
A rendered file is kept under the exact request that produced it: the url, and every option you sent with it. Change any of them, a viewport, an image format, a selector, and you have described a different picture, so the page is rendered again. A screenshot and a PDF of one page are two entries for the same reason.
Entries belong to your own account. Nobody else's request is ever answered with a rendering you paid for, and yours is never answered with theirs, so what you render stays between you and us.
Identical requests that arrive at the same time are rendered once rather than once each. If you fan a batch of workers out over the same page, the first one renders it and the others are handed the result.
The cache is also how an asynchronous batch hands its
results over. There is no response for a queued render to travel back in, so the rendering is kept here and the
batch gives you a link that fetches it. That is why an item of a batch may not turn caching off, and why its
cacheTtl has a floor of its own.
What it costs
A cached answer costs no credit. We render nothing, so there is nothing to charge for, and the answer arrives without waiting for a browser.
It is counted against a rate limit of its own rather than against the one your renders come out of: 300 cached answers per minute, the same for every account whatever plan it is on. That is far more room than the render limit gives you, which is the point. A page that fetches twenty thumbnails the moment it loads is twenty hits, and it should not be able to spend a minute of the renders you were saving for real work.
Because a hit costs us nothing, it is served even when your credits have run out or your plan has lapsed. A request that has to render is refused in that situation; one we can answer from a rendering you already paid for is not.
Reading the headers
Every rendered answer says where it came from.
-
Name
X-CacheTypestringDescriptionHITmeans the file came out of the cache, so nothing was rendered and no credit was spent, and theX-RateLimitheaders beside it report the cached budget of 300 rather than your render limit.MISSmeans the page was rendered for this request and the result was kept for the next one. The header is absent altogether when you sentcache=0: that request declined the cache rather than missing it. -
Name
ETagTypestringDescriptionA quoted fingerprint of the file itself, so two renderings that produced the same bytes carry the same tag. Keep it alongside whatever you did with the file and send it back on your next request to find out, for free, whether anything changed.
Asking whether anything changed
Send the ETag of the copy you already hold back as an If-None-Match header. If the
entry is still the one that tag describes, the answer is 304 with no body at all: no credit, no
file to download a second time, and nothing counted against either rate limit. It is the one answer the API
gives away entirely, so a client that polls for changes can do so as often as it likes.
A conditional request the cache cannot answer, because you sent cache=0 or because the entry has
lapsed, renders the page first and then compares. If the fresh bytes carry the tag you hold, that is a
304 with no body too. This one costs what the render costs, a credit and a slot of your render
budget, because the page had to be loaded to find out. What you save is the download, and the answer carries
the X-RateLimit pair to say which budget paid for it.
Anything else is answered normally, with the file.
curl "https://api.screenshotbuddy.io/v1/snap?url=https%3A%2F%2Fexample.com" \
-H "Authorization: Bearer {token}" \
-H 'If-None-Match: "<etag>"' \
--output screenshot.png
Watching a page for changes
Put the two together and you have a monitor. Send cache=0 with the If-None-Match of
the last capture you kept, as often as the page deserves. A 304 means the page still looks exactly
as it did. A 200 means it does not, and the body is the new capture, carrying the new
ETag to hold for the next round.
Every round really loads the page, so what you are told is about the page rather than about our cache, and every round costs one render. That is the price of finding out.
Branch on the status rather than on the file you were writing to. A 304 has no body, so a
downloader pointed straight at the copy you are keeping would empty it; write to a scratch name and keep it
only when the status was 200.
curl "https://api.screenshotbuddy.io/v1/snap?url=https%3A%2F%2Fexample.com&cache=0" \
-H "Authorization: Bearer {token}" \
-H 'If-None-Match: "<etag>"' \
--write-out "%{http_code}\n" \
--output capture-new.png
How long a rendering is kept
A rendering is kept for 86400 seconds unless you say otherwise. Send cacheTtl, in
seconds, to choose your own: at least 60 and at most
2592000, which is thirty days. Pick it from how often the page changes rather than from
how often you ask: a marketing page can sit at the maximum, a dashboard should not.
Once the time is up the next request renders the page again, and costs a credit again.
Always rendering afresh
Send cache=0 and the page is rendered as it is right now. That request neither reads the cache nor
fills it, it carries no X-Cache header, and it costs a credit like any other render. Sending
cacheTtl alongside it is rejected with a 422: there is no lifetime to set on a
rendering that is not being kept.
Try the options before you cache them
Get the request right in the browser first. A cached rendering is only as useful as the request that made it, and the playground is where you find out which options you actually want.