Privacy Policy
screenshot-api.net is operated by Caio Ricciuti (“we”, “us”), an individual sole operator, acting as the data controller for the data described below. This policy covers the website, the dashboard and the rendering API. It is written to be read, not to be survived.
1. The short version
- We do not store your screenshots unless you ask us to. A plain capture is rendered, returned in the HTTP response, and never written to disk or a database. Baselines, comparisons and snapshot sets exist to remember pages, and keep what they need — see section 3.
- The render log keeps hostnames, not URLs. It records
example.com, never the path, query string or fragment. Our web server’s access log is different: it records the request as sent, so a target URL you put in aGETquery string is in it for up to 90 days. - We ask for an email address and nothing else. No name, no company, no phone number, no address.
- We never see your card. Payments run entirely inside Stripe.
- We do not sell data, run ad trackers, or share anything for marketing. Analytics is self-hosted and cookieless.
- Everything lives on one server in Helsinki, Finland, inside the EU.
2. What we collect
Your account
Your email address, the plan you are on, the date you signed up, and — once you subscribe to a paid plan — the Stripe customer identifier that links your account to your billing record. There is no password to store: you sign in with a single-use link sent to your email.
API keys
We store a SHA-256 digest of each key and its first 16 characters, so the dashboard can show you which key is which. The key itself is never written down. It is shown to you once, at creation, and after that we could not recover it if we wanted to. We also record when a key was created, when it was last used, and whether it has been revoked.
Usage and metering
A counter of renders per calendar month per account, which is what your quota is measured against.
The render log
One row per capture, holding: your account id, the hostname of the target page, the output format, the size of the image in bytes, how many milliseconds it took, whether it succeeded, and the timestamp. This is what draws the charts on your dashboard and what we look at when you tell us something is slow or broken. It is deleted after 90 days.
Sign-in tokens and sessions
Sign-in links and session tokens are stored only as SHA-256 digests, alongside their creation and expiry times. A sign-in link is single-use and expires after 20 minutes; a session expires after 30 days.
Server logs
The web server writes an access log containing IP address, timestamp, the requested path and query
string, response status, response size and user agent. The query string is recorded as sent: if
you call GET /v1/screenshot?url=…, the target URL is in this log, and so is an API key
passed as ?key=. To keep both out of it, send the request as POST with a JSON
body and the key in the Authorization header, which is never logged. These logs exist to
debug faults and to spot abuse. They rotate by size, old files are discarded after 90 days at the latest,
and we do not archive them.
The public demo
The demo on the home page runs without an account. To keep it from being used as a free rendering farm we hold your IP address in memory only for an hourly rate-limit counter. It is never written to disk and it is gone when the process restarts.
Waitlist
If you gave us an email address for a feature waitlist, we hold that address and where you submitted it, until the feature ships or you ask us to delete it.
3. What is kept, and what is not
This is the part people actually want to know, so it gets its own section. The short answer: a plain capture leaves nothing behind but a hostname; the features whose job is to remember a page keep what that job needs, for as long as you keep using them.
Plain captures
- Each capture runs in a fresh, isolated browser context that is destroyed when the render finishes. Cookies,
localStorageand HTTP cache never carry from one customer’s render to another’s. - A capture from
/v1/screenshot,/v1/capture, the MCP tool or the demo is streamed back in the response body. We do not write it to disk, to a database, or to any cache or CDN of ours. - The render log keeps only the hostname. The full URL is held in memory for the length of the request — apart from the web server access log described in section 2.
Features that keep things because you asked them to
- Baselines. When you store a baseline — by naming one in
/v1/compare, or as the first run of a snapshot set — we keep that image on our server together with its full URL, viewport settings, page status and capture time, so the next comparison has something to compare against. It stays until you replace or delete it, delete the set it belongs to, or delete your account. - Delivered images. A comparison posted to Slack, a changed page in a snapshot set run, and a screenshot requested from the Slack app are stored as an image for 7 days, so the message or run can link to it, and then deleted. Anyone holding the link can open it; the link contains a 128-bit random identifier and is not listed anywhere, so treat it like the image itself.
- Snapshot sets. A set stores the full URLs of its pages, its schedule and the capture options you give it. That includes any cookies, headers or basic-auth credentials for the target site, which are kept in our database encrypted (AES-256-GCM, with a key held outside the database) and decrypted only to send them again on each run. Every run records the URL and outcome of each page. A set and its runs stay until you delete the set or your account. Give a set credentials for a test or low-privilege account, never a personal one.
- Slack. If you connect Slack, we keep the incoming-webhook address you gave us, as given, and post the messages you set up to it: page URLs, a change summary, and a link to the delivered image.
We do not read, index or analyse the contents of the pages you capture, whether or not a feature keeps them.
Images from the API carry Cache-Control: private, no-store, so no proxy or CDN between us
and your client is allowed to keep a copy. What happens to the image once your code has it is up to you;
if you capture something sensitive, store it accordingly.
4. Why we are allowed to
Under the GDPR, each thing we do rests on one of these legal bases:
| What | Basis |
|---|---|
| Running your account, issuing keys, metering quota | Performance of a contract (Art. 6(1)(b)) |
| Taking payment and issuing receipts | Performance of a contract (Art. 6(1)(b)) |
| Keeping invoices and payment records | Legal obligation — tax and accounting law (Art. 6(1)(c)) |
| Server logs, rate limiting, abuse prevention, security | Legitimate interests — keeping the service up and not being abused (Art. 6(1)(f)) |
| Aggregate, cookieless traffic statistics | Legitimate interests — understanding what the site is used for (Art. 6(1)(f)) |
| Waitlist emails | Consent (Art. 6(1)(a)), withdrawable at any time |
5. How long we keep it
| Data | Kept for |
|---|---|
| Account email, plan, signup date | As long as the account exists, then deleted within 30 days of your deletion request |
| API key digests | Until you revoke the key or delete the account |
| Monthly usage counters | Life of the account — they are your billing history |
| Render log (hostname, size, duration) | 90 days, then automatically deleted |
| Baselines (image, full URL, settings) | Until you replace or delete them, delete their set, or delete the account |
| Delivered images (Slack, set runs) | 7 days, then automatically deleted |
| Snapshot sets, their options and credentials, and run history | Until you delete the set or the account |
| Slack webhook address | Until you disconnect Slack or delete the account |
| Sign-in tokens | 20 minutes, or until used |
| Sessions | 30 days, or until you sign out |
| Server access logs | Until rotated out by size — 90 days at most, never archived |
| Demo rate-limit IPs | In memory only, roughly an hour |
| Invoices and payment records | As long as tax and accounting law requires |
| Backups | 14 nightly snapshots, then overwritten. They copy the database, so they include set URLs, options and credentials and baseline URLs — but no images |
Deleting your account removes your email, keys, usage rows, render log, baselines, delivered images, sets, runs and Slack connection. Payment records held by Stripe, and anything we must keep for tax purposes, survive that deletion because the law requires it.
6. Who else touches it
The list is short on purpose. Every one of these is a company we pay to do one job.
| Provider | What for | Where |
|---|---|---|
| Hetzner Online GmbH | The server everything runs on, and the mail server that sends sign-in links and account email | Helsinki, Finland (EU) |
| Stripe Payments Europe, Ltd. | Subscriptions, cards, invoices, the billing portal | Ireland (EU), with transfers to Stripe, Inc. in the US |
Slack receives data only if you connect it, and then only what you set up to be posted to your own workspace: page URLs, change summaries and links to delivered images. Slack is your provider, chosen by you, rather than one we engage; its processing happens in the United States and is covered by your agreement with Slack.
Analytics is self-hosted on our own infrastructure and is not a third party. There is no CDN, no tag manager, no advertising network, no session recorder, and no customer-support widget.
Business customers can find the same list, in contractual form, in the Data Processing Addendum. We will give notice there before adding a subprocessor.
7. International transfers
Your data is stored in Finland, and our email is sent from our own mail server there. One provider involves a transfer outside the EEA: Stripe, which may route data to its US entity. That transfer is covered by the European Commission’s Standard Contractual Clauses. The only personal data leaving the EEA is what Stripe holds for billing, your email address and billing details — plus, if you connect Slack, the messages you asked us to post to your workspace.
8. Cookies
We set two cookies, both strictly necessary, neither used for tracking. There is no cookie banner because there is nothing to consent to.
| Cookie | Purpose | Life |
|---|---|---|
sa_session | Keeps you signed in. HttpOnly, Secure, SameSite=Lax; holds an opaque token whose digest is what we store. | 30 days |
sa_auth | A flag with no secret in it, readable by the page so the navigation can render a signed-in state without a round trip. | 30 days |
Signing out deletes both. Your browser’s theme preference is kept in local storage, not in a cookie.
9. Analytics
We run a self-hosted Umami instance on our own server. It is cookieless, sets no
identifier, does not follow you between sites, and produces aggregate counts: pages viewed, referrer,
country, browser family. No data reaches a third-party analytics company because there isn’t one.
Page addresses are recorded without their query strings. A browser sending Do Not Track, or
any ad blocker, will suppress it entirely, and nothing on the site depends on it.
10. Personal data in the pages you capture
When you point the API at a URL, whatever is on that page may contain personal data — names, faces, comments, a signed-in user’s own dashboard. For that data you are the controller and we are your processor: we render what you ask for and hand it back. We keep none of it, except what a baseline, a delivered image or a snapshot set is there to keep (section 3).
That split carries obligations for you as well as for us. You must have a lawful basis and the right to capture the page — see the Acceptable Use Policy — and if you need a signed processor agreement, the Data Processing Addendum is it.
11. Security
- Everything is served over TLS. HTTP is redirected, and HSTS is set.
- API keys, sign-in links and session tokens exist in the database only as SHA-256 digests, so a copy of the database yields no working credentials for this service. Target-site credentials given to a snapshot set, and a connected Slack webhook address, are the exception: they have to be sent again, so they are stored encrypted (AES-256-GCM, with a key held outside the database) rather than as digests.
- Pages are rendered by a headless browser running as an unprivileged user with the browser’s own sandbox switched on: each page’s renderer process is confined to its own user, process and network namespaces under a system-call filter. The browser container holds no kernel capabilities, has a read-only filesystem and filtered network egress, and its browser version is pinned and updated deliberately.
- Every address a page asks for — the URL you submit, redirects and every subresource — is checked against private, loopback, link-local and reserved address ranges before the browser is allowed to fetch it.
- The host runs a default-deny firewall; only ports 22, 80 and 443 are reachable, and SSH is key-only.
- Backups are taken nightly, kept for 14 days, and readable only by the operator.
- Card data never touches our servers.
No system is perfect. If you find a security problem, please write to me@caioricciuti.com before disclosing it publicly; we will not pursue anyone who reports a flaw in good faith and does not exfiltrate or destroy data.
If a breach affects your personal data and is likely to put you at risk, we will notify you and the relevant supervisory authority without undue delay.
12. Your rights
If you are in the EEA or the UK, you have the right to:
- ask what we hold about you, and get a copy;
- have inaccurate data corrected;
- have your data deleted;
- restrict or object to processing we base on legitimate interests;
- receive your data in a portable format;
- withdraw consent where consent is what we relied on;
- complain to your national data protection authority — ours is the Spanish Agencia Española de Protección de Datos (AEPD).
Write to me@caioricciuti.com from the address on the account. We answer within 30 days, usually much sooner, and we do not charge for it. There is no automated decision-making and no profiling.
13. Children
This is a developer tool and is not directed at children. We do not knowingly hold data about anyone under 16. If you believe we do, tell us and we will delete it.
14. Changes
We may update this policy. The date at the top always reflects the current version, and material changes will be announced by email to account holders before they take effect.
15. Contact
Caio Ricciuti, sole operator of screenshot-api.net — me@caioricciuti.com. We have no Data Protection Officer; there is no separate department to route you to, so that address reaches the person who runs the service. The operator’s tax ID and the other details Spanish law requires are in the Legal notice.