Skip to main content
BotScore · Legal

Privacy policy

Your resume is read in memory, scored, and thrown away. The score is what we keep — and this page lists every field of it, including the parts we haven’t finished building.

Last updated 27 July 2026

The scan record, field by field

One row is written per scan. This is all of it.

Kept

scan id
a random identifier for the row itself
file name
the name of the file you uploaded
file type
PDF or DOCX, the only two we accept
content hash
a SHA-256 fingerprint of the file’s bytes, used as a cache key
target role
the job title you typed
overall score
the 0–100 number
dimensions
the per-dimension scores behind it
fixes
the changes we suggested
parse flags
what the parser found: tables, columns, images
summary
the model’s written explanation of the score
keywords
terms found in your resume and terms missing from it
created at
when the scan ran
owner
your account ID if you were signed in; otherwise an unguessable claim token
ip hash + day
stored in a separate counter table, not on the scan (§5)

Never kept

the file itself
parsed in memory; never written to a disk, a bucket or a column
the text inside it
extracted, sent to the scorer, discarded when the request ends
your IP address
only the hash in the left column, never the readable address
card details
BotScore takes no payment, so there is nothing to collect
your resume in analytics
no file, no text and no file name is ever sent to PostHog or Google
training data
BotScore has no training pipeline; we do not use your resume to improve any model
anything sent to employers
no employer, recruiter or job board receives your resume or your score; there is no such integration

A hash can be checked against a file you already have. It cannot be turned back into your resume.

What this policy covers

This policy covers the BotScore website and the automated resume-scoring service running on it. It describes what the service does today. Where the product doesn’t yet do something people reasonably expect, this page says so instead of implying otherwise.

For anything about your data, use the contact form.

Your resume file

When you upload a resume, the file is parsed in memory to pull out its text. Neither the file nor the extracted text is written to a database, a storage bucket or a log — both exist only for the length of the request and are gone when it ends. There is no storage bucket in BotScore and no column that holds resume text.

One thing is derived from the file and kept: a SHA-256 hash of its bytes. Paired with the target role you typed, that hash lets an identical re-upload return the score we already produced instead of paying for another model run. It is a cache key and nothing else — it never grants access to a scan.

What a scan record contains

The ledger at the top of this page is the complete list. Scan records are stored in a Postgres database hosted by Supabase and protected by row-level security, so a signed-in row can be read only by the account that owns it.

If you scan without an account, the row is stored with no owner and an unguessable claim token, which is also set as a cookie in your browser. The next sign-in from that browser attaches the scan to whoever signed in — a brand-new account, or one that already existed.

So the binding is a cookie in a browser, not proof of who wrote the file. On a shared computer a scan can land on the wrong person’s account, which is why the dashboard names any scan it has just attached. Until a sign-in happens, an anonymous scan isn’t connected to you in any other way — which has a consequence, in §10.

The models that do the scoring

BotScore does not score your resume by itself. To produce a score we send the extracted resume text, the target role you typed and the parser’s structural flags to a third-party model provider: OpenAI first, and xAI as a fallback when OpenAI is unavailable or busy. Whichever provider answers first is the one that sees your text.

Those providers process the request on their own infrastructure under their own terms, and we don’t control how long they hold it. Nothing else travels with the request — not your email address, not your account ID, not the name of your file.

Rate limits and hashed IP addresses

Two things here are capped per day, and both are counted against a hash rather than an address: scanning without an account, because every scan that reaches a model costs money, and sending the contact form, because it reaches a person. In each case the server stores a SHA-256 hash of your IP address combined with the UTC date, together with a counter. The raw address is never written down. Those rows are readable only by the server — no browser session can reach them.

Plainly

A hashed IP address is still information about you. We could have left it out of this page and most people would never have known, so we’re naming it: if you scan anonymously or send us the contact form, a hash derived from your address exists in our database for the day you did it.

Accounts

Accounts are handled by Supabase Auth. You can sign up with an email address and a password, or continue with Google. We store your email address, an account ID and which method you used; password resets are sent to your email address.

If you arrived from one of our ads, the Google click ID and campaign name are copied onto your account record once, the first time they’re seen, so we can tell which campaign led to which signups.

Cookies, analytics and advertising

Six things on this site set cookies or send data off the page:

  • Session cookies — set by Supabase Auth to keep you signed in.
  • bs_anon_scans — an httpOnly cookie holding the claim token for an anonymous scan so it can be attached to an account signed in from this browser. It lasts 24 hours.
  • bs_scan_claimed — names the scans that were just attached to your account, so the dashboard can tell you which ones moved. It lasts about five minutes and, unlike the cookie above, your browser can read it — dismissing that notice is what deletes it. It carries no access to anything.
  • bs_attrib — a first-party cookie holding the Google click ID and campaign from the ad you clicked. It lasts seven days and is copied onto your account record if you sign up.
  • The Google Ads global site tag — gtag.js loads on every page of this site. It sets Google’s own advertising cookies, and Google receives that you visited plus conversions such as a completed signup. Google uses this for conversion measurement and remarketing; their handling is described in Google’s advertising policy.
  • Product analytics (PostHog) — loaded through a same-origin /ingest path on this domain and sent to PostHog’s US region. It records page views and product events — a scan started, a score revealed, a signup, a click on a priced button — against a random visitor ID. Once you sign in we tie that ID to your BotScore account ID. If you send us feedback through the feedback box, the text you typed is sent with that event.

Two small values sit in your browser’s own storage rather than in a cookie: the time of your last visit, and a marker so the feedback box appears at most once. Neither is transmitted — though the number of days since your last visit is reported to PostHog as a product event.

Companies that process data for us

These are the companies that handle data on our behalf, and what each one gets:

  • Vercel — hosts the site and runs the scanning code.
  • Supabase — the database holding scan records, and the accounts and sessions behind sign-in.
  • OpenAI and xAI — receive the extracted resume text and target role in order to score them.
  • PostHog — product analytics, in its US region.
  • Google — advertising and conversion measurement through the site tag, and Google sign-in if you choose it.

How long we keep things — and what we don’t do yet

Deleting a BotScore account removes its scans and its recorded interest in a paid plan along with it: those rows are tied to the account with a cascading delete at the database level, so they go when the account goes.

Plainly

Three things are true today and we’d rather you heard them here than found out later:

There is no self-serve deletion screen. Deleting your account is a request you send through the contact form, not a button you press.

There is no automated retention or expiry job. Records are not aged out on a schedule. They stay until an account is deleted, and we’re not going to state a retention period we don’t enforce.

Scans made without an account survive account deletion. An anonymous scan is stored with no owner, so it isn’t connected to any account and deleting one doesn’t remove it. To have an anonymous scan removed, use the contact form and give us the file name and roughly when you ran it.

Asking for a copy, a correction or a deletion

Ask for a copy of what we hold about you, a correction, or a deletion through the contact form. Tell us the email address on your account — or, for an anonymous scan, the file name and roughly when you ran it, which is what we have to search on.

The form makes a record of its own: the email address you give it, which kind of request you picked, your message, the time, your account ID if you were signed in, and the hashed IP address and day used for its daily cap (§5).

Requests are handled by a person rather than a system today, so allow a few days for a reply.

Changes to this policy

When this policy changes, the date at the top of the page changes with it. If a change materially affects what we collect or who receives it, we’ll say so on this page rather than alter it quietly.