Privacy policy
Last updated: 2026-09-20
Summary
Reading reactions needs no account and no sign-in. To show a count, the extension asks our server for the public identifier of each supported item that scrolls into view; that lookup carries no account, no installation identifier, and no cookie, and the server neither stores nor logs which identifiers were asked
for. To submit your own reaction you
sign in once through a provider you already use (Google, Apple, Microsoft or Twitch); the request asks the provider for the standard openid scope only, so no name, email or picture reaches us. Only a one-way keyed hash of the opaque id the provider
assigns you, plus the provider's name, is persisted as your account record. You can delete that record at any time from the extension settings.
Website analytics and extension reaction context. On emojery.app, the marketing site you are reading right now, we use 2 complementary analytics layers: Google Analytics (loaded through Google Tag Manager, cookie-based, consent-gated in the EEA, the UK and Switzerland, on by default elsewhere) and Cloudflare Web Analytics (cookieless, aggregated traffic counts only, no user identifiers). Decline the cookie banner and the site works exactly the same. The browser extension itself does not load Google Analytics, Cloudflare Web Analytics, or any other analytics SDK. Active reaction rows keep timestamps and an active-row count of reaction changes. Each reaction submission includes the current "Community insights" setting value. When that setting is enabled (default; you can opt out in extension settings), reaction submissions also carry context for aggregate maps: country and city, language, browser family, and operating system.
For what the extension can technically access in your browser, and why each permission exists, see Browser permissions.
What we collect
- Your sign-in provider's opaque id, only as a keyed hash. When you sign in, the provider hands our server an id that means "this account" to the provider and nothing to anyone else, together with the provider's name. The id itself is used once, to compute a one-way keyed hash, and is not written to a database; the hash and the provider name are your account record. The key that produces the hash is held outside the database, so a copy of the database on its own yields no ids and cannot be tested against a guessed provider account; we hold that key, so we can check whether a provider account you name has an Emojery account, which is what an access or deletion request needs. Your name, email address and picture are never received, because the sign-in never asks the provider for them.
- The public halves of your signing keys, and your enrollment proof. Once every 30 days the extension creates a signing key on your device; the private half never leaves it. Our server signs the public half blind (it cannot see which key it signs) and the public half, the blind signature and, once per account, a zero-knowledge proof that the account came from a real provider sign-in are appended to the public transparency log. None of them carries the provider's id or anything a provider could match against its records; the pseudonym on your reactions is derived from the key.
- The public identifiers of items on screen, to show their counts. On a supported page the extension asks the server for the count of each item that comes near the viewport, whether or not you react to it, by sending its canonical target key (for example
youtube/<video-id>). That request carries no account, no installation identifier, and no cookie. The server answers it, does not store it, and logs only the request path without the identifier. While you are signed in, a second request asks which of the items on screen you have already reacted to; it carries your session token and up to 50 target keys at a time, and it is likewise answered without being stored or logged with its keys. Neither request leaves a record on the server of what you looked at. - The reactions you submit and the public target you reacted to (e.g. a Facebook post URL or a GitHub repo). The submission carries the canonical URL of the item, rebuilt from its identifier with tracking parameters dropped; on X and Threads that URL includes the author's handle, as every permalink there does. The server derives the target key from that URL and keeps the key, not the URL. Aggregate counts are kept indefinitely; per-user reaction records include row timestamps and how many times the active row has changed. A per-user record exists for as long as its reaction stands — removing the reaction, or deleting your account, removes it immediately, and every period is set out in How long we keep it. Each accepted reaction is also appended (under a rotating pseudonym, never your email, account identifier, or anything linkable to them without a secret key only our backend holds, and timed only to the minute) to the public, append-only transparency log that makes the counters verifiable.
- Reaction context, unless you turn it off. For targets you explicitly react to, each reaction submission sends your current “Community insights” setting. When it is on, the backend stores, with that reaction record, the country and city Cloudflare
derives from your connection, the primary language from
Accept-Languageor the extension fallback, the browser family, and the operating system. City is the finest of these and is stored as a name, not as a coordinate; nothing finer than a city is ever derived. The setting starts on. Turn off "Community insights" in extension settings to send an opt-out and store the context fields as empty for future reactions; reactions already stored keep the context they were submitted with until you remove them. - Bug reports, only if you send them. The extension popup's Report tab submits the page address (stripped of everything but the identifying query parameter), its host, which supported site it is, how many reactable targets the extension found on it, and the note you wrote. When “Community insights” is on, the submission also carries the extension version and your browser's raw user-agent string — unlike reaction context, it is not reduced to a browser family, because reproducing a layout bug needs the exact browser build. It is stored with the report under your internal account identifier, shown to the maintainer, and also posted to the maintainer's private alert channel (see Subprocessors). Turn the setting off and both fields are omitted. A report is kept after you delete your account, which is set out in How long we keep it.
- A session token stored only in your extension's local storage. Lets you react without re-entering a code each time; it expires on the schedule in How long we keep it, after which you sign in again. The extension also keeps the address you signed in with in that same local storage, only to label the account in the popup; after sign-in it is sent once more only if you delete the account, so that the farewell message can be addressed.
- A salted hash of your IP address: a hash that changes every day, used only to rate-limit abuse against the sign-in start, report, API-waitlist, uninstall-feedback, and read endpoints. Two uses touch the raw address without storing it: the per-address request limiter that every request passes through, which runs on Cloudflare's rate-limiting service and holds nothing beyond a counter for the current window, and the Turnstile bot check on the 2 website forms, which receives the address to score the submission. One hash does not rotate: the roadmap page on this website records a fixed salted hash of your address next to each upvote, so the same person cannot upvote one entry twice; it is kept for 365 days.
- A random installation identifier, and a daily session identifier derived from it. The extension generates the installation identifier itself: a random value, never derived from your device, your browser, or anything about you, and it carries no personal data. It accompanies only the requests you initiate that change something: signing in and out, submitting or removing a reaction, filing a report, and deleting your account. Reading counts sends nothing of the kind. Our backend stores it only as a salted hash, computes the session identifier from that hash and the calendar day (the extension does not send one), and uses both to keep abuse and duplicate-account activity off the public counters. The session you open when you sign in is tied to your installation identifier, so a sign-in token presented from a different installation is refused. The installation identifier lasts until you remove the extension; the session identifier changes every day. Both hashes are stored alongside your account record and your reaction records, and deleting your account removes them from there. A separate first-seen/last-seen ledger keyed by the hashed installation identifier alone, with no link to any account, is kept for 90 days after the installation was last seen and is not touched by account deletion.
- On Firefox, one more header. Every request the extension makes names the browser runtime it comes from, so the server can tell a browser extension from a script. On Chrome and Edge that value is the same for every installation. On Firefox the browser assigns each installation a random internal address, so the header is unique per installation there, as is the Origin header the browser itself adds. The server compares the scheme, does not store either value, and strips the installation part from both before anything is written to a log line or an alert.
- Anti-abuse records about individual reactions. When a reaction trips an abuse check, the backend records the decision with your internal account identifier, the target, the emoji, the network's autonomous-system number, and the signals that fired; a review of accounts that share an installation or vote in lockstep records the account identifiers and targets involved. These records exist to keep manufactured votes off the counters and are kept on the schedule in How long we keep it, including after account deletion, because a deleted account is the usual next step of someone evading a ban.
- API-waitlist email, only if you opt in. If you join the API waitlist on this website, we store the address you enter until the launch announcement is sent. See the API waitlist section below.
- Uninstall-survey answers, only if you send them. The page your browser opens when you remove the extension has an optional feedback form. If you submit it we store your answers, and the email address only if you chose to leave one. See the uninstall feedback section below.
What we do not collect
- No real name.
- No email address, and no name or picture. The sign-in asks the provider for the standard
openidscope only, so none of them ever reaches our server. The only places an email address is stored are the 2 optional forms on this website: the API waitlist and the uninstall survey. Both are described below, and both store an address only because you typed one in and asked to be written to. - No raw IP address stored on the reactions backend.
- No high-entropy browser fingerprint, hardware identifiers, or cross-site advertising profiles. Reaction context is a browser family and an operating-system name, not a version string or a hardware probe. The single exception is the raw user-agent string on a bug report you choose to submit, described above. It is diagnostic data attached to that one report, never collected in the background and never used to profile you.
- No advertising cookies, no remarketing pixels, no ad-network SDKs. Google Analytics is loaded on this website only, for first-party traffic measurement, under the regional consent rules in Website analytics and cookies; we run no ads and no remarketing, and nothing is shared with the Google Ads ecosystem.
- No stored record of pages you did not react on. The count lookups described above send the identifiers of items on screen and are answered without being stored or logged with those identifiers. The one way a page you did not react on reaches our database is a bug report you file about it.
- No server-side copy of your reaction history. The list of your recent reactions shown in the extension popup is stored only in your browser's local extension storage and is never uploaded to our servers.
- No password. We deliberately don't operate a password database — your provider's own sign-in is the authenticator.
Website analytics and cookies
Where this applies: only the marketing website emojery.app. The browser extension itself does not load Google Analytics, Google Tag Manager, or any analytics SDK. Extension reaction context is first-party data sent only with reaction submissions, controlled by the extension setting described above.
We use Google Tag Manager to load Google Analytics 4 on the website. We use it to understand how many people land on the install page, which articles get read, which referrers send the most traffic, and a country-level breakdown of visitors. We do not run ads, we do not use Google Signals (cross-device audiences), and we do not run remarketing.
Whether the cookies are set depends on where your browser says you are. The site reads the time zone your browser reports and treats a European, UK or Swiss zone as a visit from the EEA, the UK or Switzerland. For those visits, Google Consent Mode v2 keeps every storage type denied until you click Accept on the consent banner: page views are counted in an anonymized, cookieless mode and the request identifier is reset every 24 hours, and if you decline, that mode persists for the rest of the session. For every other visit the banner is not shown and the analytics cookies are set on the first page view; there is no in-page switch to refuse them, and the ways to opt out are listed in the cookie policy.
For the full cookie inventory (names, lifetimes, providers, and the cookieless layer) see the dedicated
cookie policy. In short: 2 first-party GA4 cookies (_ga and a _ga_* per-property one), plus 3 localStorage keys that hold choices you made on this site: your banner decision (emojery-consent-v1), your theme (theme), and
your roadmap upvotes (em_roadmap_liked).
To change your decision later, clear your browser's cookies and
localStorage for emojery.app — the consent banner will reappear on next visit. The
cookie policy has step-by-step instructions.
Cloudflare Web Analytics (cookieless)
In addition to Google Analytics, we also use
Cloudflare Web Analytics, which runs alongside GA but works completely differently. It is cookieless, sets no
localStorage, does not assign user identifiers, and produces only aggregated, anonymous traffic numbers (visits, top pages, referrer source, country, browser).
Because no information is stored on your device by Cloudflare Web Analytics, it is not gated behind the cookie banner. It processes server-side aggregates under our legitimate interest (Art. 6(1)(f) GDPR) in keeping the site healthy and understanding its traffic. There is nothing to opt out of at the cookie level because nothing is set on your device. If you would prefer that we exclude your visits entirely, a browser-level "Do Not Track" or a Cloudflare-blocking extension (uBlock, AdGuard, Privacy Badger) will hide your visit from this layer as well.
Where data lives
- Your account record and reactions are stored in a managed database, encrypted at rest, located in either the EU or the US depending on the region you were assigned at sign-in.
- Short-lived items live only in ephemeral edge storage that deletes them on a fixed timer — minutes for the state of a sign-in in progress, hours for replay-protection tokens. They are never written to the long-term database.
- All traffic between your browser and our servers is encrypted in transit.
- Aggregate per-target counts are kept indefinitely so the extension can keep displaying them. Your per-user reaction record includes the context listed above while your reaction is active. Deleting your account removes your account record, your reaction records and your live anti-abuse counters immediately and adjusts the aggregate counters accordingly; the pseudonymous entries in the public transparency log are reversed by public revocation entries rather than deleted, and the few records that outlive an account are listed in How long we keep it — see Your rights.
- Your reaction history, the list shown in the extension popup's History tab, is stored only in your browser's own extension storage, in full and with nothing trimmed away as it grows. It never reaches our servers, and it is cleared when you delete your account or uninstall the extension.
How long we keep it
One row per thing we hold. Where a row says "immediately", it means the delete runs inside the request you triggered rather than on a nightly job.
| What | How long it is kept | Where it lives |
|---|---|---|
| One-time sign-in code | 10 minutes, or until you use it — whichever comes first. | Ephemeral edge storage |
| Session token | 30 days, then it stops working and you sign in again. Signing out drops it at once. | Your browser's extension storage |
| Replay-protection tokens, rate-limit counters, the state of a sign-in in progress | Each expires on its own timer, measured in minutes to hours. The exact windows are not published — see below. | Ephemeral edge storage |
| Your account record — the one-way keyed hash of your provider's opaque id and the provider's name, plus the hashed installation identifier and the daily session identifier derived from it | Until you delete the account, which you can do yourself from the popup's Account tab. Deletion is immediate. | Managed database (EU or US region) |
| An active reaction — the target, the emoji, the row timestamps, the count of changes, and the country, city, language, browser and OS context if you left “Community insights” on | For as long as that reaction stands. Removing the reaction, or deleting the account, removes the record immediately. | Managed database (EU or US region) |
| Aggregate counts per target | Indefinitely — they are the numbers the extension displays. Your contribution to them is decremented the moment you remove a reaction or delete the account. | Managed database (EU or US region) |
| Entries in the public transparency log, under a rotating pseudonym | Permanent by design. Deletion appends a public revocation that reverses the entry; it cannot erase it, and neither can we. | Public log repository, mirrored by third parties |
| A bug report you sent from the Report tab — the page address, your note, and the user-agent string and version if you left “Community insights” on, filed under your internal account identifier | Until removed by hand. There is no automatic sweep, and deleting your account does not delete it: the identifier it carries then points at no account, but the address and the note stay. Removed on request. | Managed database (EU or US region) |
| The installation ledger — first-seen and last-seen times keyed by the hashed installation identifier alone | 90 days after the installation was last seen. Not linked to an account and not touched by account deletion. | Managed database (EU or US region) |
| Roadmap upvote marker — a fixed salted hash of your IP address next to each roadmap entry you upvoted on this website | 365 days. | Managed database (EU or US region) |
| Uninstall-survey answer, and the email address only if you left one | Until removed by hand, which happens once it has been read and, where you asked for a reply, answered. There is no automatic sweep. Removed earlier on request. | Managed database (EU or US region) |
| API-waitlist address | Until the single launch announcement is sent, after which the waitlist is deleted by hand. Removed earlier on request. | Managed database (EU or US region) |
| The provider-id hash of an account terminated for abuse | Kept after deletion, without an end date, for the single purpose of enforcing the termination — see Your rights. | Managed database (EU or US region) |
| Live anti-abuse counters derived from the hashed identifiers above (how many accounts one installation has signed in, how many reacted to one target from one network in a day, and the like) | Each row expires on its own timer and is swept on a schedule. The windows are not published — see below. Deleting your account removes your rows at once. | Managed database (EU or US region) |
| Abuse decisions about individual reactions — internal account identifier, target, emoji, network number, and the signals that fired | 90 days from the decision. Kept after account deletion. | Managed database (EU or US region) |
| Reviews of linked accounts — the account identifiers and targets of accounts that share an installation or vote in lockstep, and the operator's note on the case | While the review is open, and 90 days after it is closed. Kept after account deletion. | Managed database (EU or US region) |
The windows we do not publish
One family of period in the table above is stated as a criterion instead of a number: how long the rate-limit, lockout, replay and live anti-abuse windows run. Publishing them would be publishing the waiting time — the exact interval to sit out between attempts in order to stay under a limit that exists to keep automated voting off the counters. That is an abuse manual rather than a privacy disclosure, and the people it helps are not the ones this page is written for.
What we will commit to instead: every such window is bounded, each is enforced by an expiry the record carries with it rather than by anyone remembering to delete it, none is exempt from anything else on this page, and a supervisory authority or a court asking for the actual figures gets them. The 2 records that do outlive an account, abuse decisions and reviews of linked accounts, carry the fixed periods stated in the table.
Subprocessors
We rely on a small number of third-party providers, each acting as a data processor under GDPR and similar regimes:
- Cloudflare: infrastructure provider for our backend services and this site. Additionally provides cookieless first-party Web Analytics (aggregated traffic numbers; no cookies, no user identifiers, no consent banner required, see the dedicated section above), supplies coarse request metadata such as country/city to the backend, and runs the Turnstile bot-check on the API-waitlist and uninstall-feedback forms.
- Neon: managed database provider for the data we persist.
- Google, Apple, Microsoft and Twitch, as sign-in providers: the one you pick vouches for your sign-in in its own window and hands our server an opaque id for your account. A provider acts as your identity provider under its own privacy policy rather than as our processor: it learns that your
account signed in to Emojery and when, and nothing after that, since the extension never contacts it again until the session expires. We ask it for the standard
openidscope only. - Google (Tag Manager and Analytics 4): first-party website analytics on emojery.app, under the regional consent rules above. Data processed includes the page URL, referrer, screen size, browser/OS, and a coarse country derived from IP. The browser extension does not use Google's services.
- Axiom: log storage for the backend. Every structured log line the backend writes is kept by Cloudflare for 7 days and exported to Axiom for 30 days. A log line never carries a raw email, a raw IP address, a raw user-agent string, or the identifiers asked for in a count lookup. It can carry your internal account identifier and a target when a reaction trips an abuse check, the country, network number and Cloudflare data center of a request that fails the extension check, and the provider name and error class of a sign-in that fails.
- Discord: the maintainer's private alert channel. The backend posts a message there when something needs a human: an abuse check firing on a reaction (your internal account identifier, the target, the emoji, the network number), a bug report (the page address, your note, and the version and user-agent string if included), an uninstall-survey answer (your answers, and the address if you left one), and sign-in failures (the provider name and the error class). Discord retains messages until the maintainer deletes them.
- DeepSeek: a language model used as a second opinion in the anti-abuse pipeline. When the backend's own checks flag a target or a group of accounts, it sends the model a summary made of counts and percentages plus the target keys involved. It never sends account identifiers, installation or session hashes, IP data, emails, or user-agent strings. DeepSeek is headquartered in China; what it receives identifies public web pages, not people.
- GitHub, Sigstore Rekor, the OpenTimestamps calendars, and Software Heritage: the public transparency log is published to a GitHub repository, its checkpoints are mirrored into Rekor and timestamped through OpenTimestamps, and Software Heritage archives the repository. What reaches them is the public log itself: pseudonymous reaction entries and signed checkpoints, nothing that is not already public.
We will update this list before adding a new subprocessor, and the change will be reflected on this page.
International data transfers
Cloudflare, Google, Apple, Microsoft, Discord, Twitch, Axiom and GitHub are US-headquartered and may route or process data on US infrastructure. Neon stores the long-lived database in the EU or the US region you were assigned at sign-in. DeepSeek is headquartered in China and receives only counts and public target keys, never personal data. Where personal data originating in the EEA, UK, or Switzerland is transferred outside those regions, the transfer relies on the European Commission's Standard Contractual Clauses (and the UK Addendum / Swiss equivalents where applicable) in our agreements with those providers. The data we transfer is minimal: chiefly the salted-hash account identifier, your reaction records and reaction context, transiently the opaque provider id at the moment you sign in, the log lines and alert messages described under Subprocessors, (under the regional consent rules, only on the website) the standard Google Analytics first-party measurement payload, and (without identifying you, only on the website) the Cloudflare Web Analytics aggregated traffic beacon.
Security
All traffic between your browser and our servers is encrypted in transit with TLS 1.2 or higher. Long-lived account data is encrypted at rest by the managed database provider. Personal identifiers we keep are one-way hashes rather than raw values, and the one standing in for your provider id is keyed with a secret held outside the database. The state of a sign-in in progress and rate-limit markers live only in ephemeral edge storage that auto-expires within minutes. We do not run a password database, so there is no password store to leak. Source code for the extension is open and auditable on GitHub. If you find a weakness, the security policy covers where to send it, what is in scope, and the terms that keep testing authorized.
That said, no method of transmission over the internet or method of electronic storage is 100% secure. While we use commercially reasonable measures to protect the limited data we hold, we cannot guarantee absolute security. If we become aware of a security incident affecting your personal data, we will notify the relevant supervisory authority within 72 hours where required by law, and notify affected users directly when the incident is likely to result in a high risk to their rights and freedoms.
Law-enforcement and government requests
Requests received to date: 0. Checked on 2026-08-24. The number is updated when it changes, and it counts every request, including ones we refused.
We respond only to valid legal process from an authority with jurisdiction over the operator, who is established in British Columbia, Canada. An order issued elsewhere is not self-executing here — it reaches us through a Canadian court or the applicable mutual legal assistance route, and anything short of that is refused. We do not disclose data voluntarily. The one exception is a credible emergency involving a risk of death or serious physical harm, where the law permits disclosure without an order; a request of that kind is counted in the line above like any other.
What could be produced under compulsion: the keyed hash of a provider's opaque id and the provider's name, the hashed installation and session identifiers, the reactions currently active on an account with the context attached to them, entries in the public log (which anyone can already read), a report or survey submission if one exists, and the abuse decisions and linked-account reviews of the last 90 days if the account appears in one. We also hold the key that links a rotating pseudonym in that log back to an account, so an order could compel that link. It cannot be derived from the published log by anyone else, and we would rather state the limit than imply an impossibility we do not have.
What does not exist to produce: your name, your email address, or the raw provider id — the sign-in never requests the first 2, and the API waitlist and the uninstall survey are the only places an email address is stored, only because you typed it in; your raw IP address; any record of which counts you read, because a count lookup is answered without being stored and its log line omits the identifier; a list of pages you visited beyond the ones you reacted on or reported; the reaction history in your popup, which never leaves your browser; and any password, since there is no password store to compel.
We cannot notify you when a request names your account. Not as a matter of discretion — we hold a hash of a provider id and never a name or an address, so there is no way to reach you. That is a direct cost of the design, and the counter at the top of this section is what stands in for individual notice.
Marketing communications
We do not send marketing emails, newsletters, or promotional content. Signing in sends you nothing. The only messages you can ever receive from Emojery are, if you explicitly join the API waitlist, a single announcement when the public API launches, and, if you leave an address on the uninstall survey, one reply to what you wrote there. There is no other list to be on; waitlist removal on request is described in the next section.
API waitlist
The /api page has an optional form for joining the waitlist of the planned public API. If you submit it, we store the email address you enter plus a keyed hash of it (used only to de-duplicate repeat signups) in our database. This is the single place where a raw email address is persisted — everywhere else only the one-way hash exists.
The address is used for exactly one purpose: a single announcement when the public API launches. It is not added to any other list, not shared with anyone, and not used for any other messaging. After the launch announcement has been sent, the waitlist is deleted. To be removed earlier, open an issue via the privacy request template and include the address you signed up with.
The form is protected by Cloudflare Turnstile, a bot-check that runs in your browser when you submit; it does not track you across sites and we never see more than a pass/fail verdict for the submission.
Uninstall feedback
When you remove the browser extension, the browser opens a page on this website with an optional survey asking why. Opening the page stores nothing beyond the ordinary website analytics described above. Submitting the form is what sends data, and only what the form shows: the reason you picked, the free-text comments if you wrote any, and an email address only if you chose to enter one.
The submission is anonymous: the extension and its session are already gone by the time the page loads, so nothing links your answers to your account, and we do not attempt to re-identify you. If you leave an address it is stored raw (the second and last exception to the hash-only rule) for the single purpose of replying to you. It is not added to any list and not used for any other messaging. To have your answer removed, open an issue via the privacy request template.
Like the waitlist form, it is protected by Cloudflare Turnstile, and a salted hash of your IP address is used transiently to rate-limit the endpoint.
Uninstalling the extension does not delete your account or reverse your reactions. Deletion runs from the extension popup, because signing in there is the only way an account can be shown to be yours: we store the keyed hash of a provider id, never a name or an address, and a message sent from an email or filed as an issue proves nothing about who controls that provider account. Delete before you uninstall, or reinstall and sign in once with the same provider account to do it afterwards. For anything the popup cannot resolve, open a privacy request.
Legal bases for processing (GDPR)
For users in the EEA, UK, and Switzerland, the legal bases under Article 6 GDPR are:
- Performance of a contract (Art. 6(1)(b)): processing your hashed account identifier, your reactions, reaction row timestamps, active-row change count, and your session token so we can deliver the signed-in features you asked for.
- Legitimate interest (Art. 6(1)(f)): short-lived, salted hashes of IP addresses and the state of a sign-in in progress, used to keep the service available and resistant to abuse; the hashed installation and session identifiers described above, which are random, carry nothing about you or your device, and let us detect duplicate-account and automated voting without profiling anyone; the abuse decisions, linked-account reviews and installation ledger kept on the fixed periods in How long we keep it, so that a ban cannot be lifted by deleting the account it was placed on; the reaction context stored under the "Community insights" setting (country, city, language, browser family, operating system), which exists so that the aggregate maps and breakdowns the product publishes can be built, is attached only to reactions you chose to submit, is stored as names and families rather than coordinates or version strings, and can be switched off for future reactions at any time from the extension settings; the logs and alerts sent to Axiom and Discord, kept so that failures and abuse can be diagnosed; and Cloudflare Web Analytics on the website, which produces aggregated cookieless traffic numbers without identifying individual visitors. We have weighed these interests against your rights and consider the hashed, pseudonymous, aggregated nature of the data proportionate. You can object to any of this processing through the channels in Contact, and for reaction context the objection is the setting itself.
- Consent (Art. 6(1)(a)): implicit in choosing a provider and approving the sign-in in its window; the opaque id it returns is used once to compute the account hash and is not retained. Explicit consent (via the cookie banner) for Google Analytics on the website for visitors from the EEA, the UK and Switzerland; for visitors elsewhere the cookies are set on legitimate interest in first-party traffic measurement, and either way you can withdraw by clearing site data or blocking the analytics host. Joining the API waitlist is consent-based: you submit the form, we store the address for the single launch announcement, and you can withdraw at any time by requesting removal. The uninstall survey is the same: nothing is sent unless you submit it, and any address on it is there because you chose to be replied to.
Automated decision-making
We do not make decisions about you using solely automated means that produce legal or similarly significant effects. Rate limits and anti-abuse checks are technical safeguards on the counters rather than profiling: an automated check can decline to count a reaction, or reverse reactions from a group of accounts that share one installation or vote in lockstep, and a language model may be asked for a second opinion on the aggregate evidence before that happens. None of this affects anything beyond whether a reaction is counted. You can ask for a human review of any such decision through Contact.
Your rights
You can permanently delete your account from the extension settings ("Delete account"). Deletion is immediate: your user row is removed, your reaction records and live anti-abuse counters are removed, and the aggregate counters for every reaction you previously submitted are decremented by one. We do not queue, review, or delay erasure requests. Four things are not removed by that step, each with the reason and the period stated in How long we keep it: a bug report you filed (removed on request), the installation ledger (90 days after last seen, not linked to an account), abuse decisions of the last 90 days, and a linked-account review that names the account. A request through Contact removes the report; the anti-abuse records are the one category we keep against the request, for the reason given in the next exception.
One structural fact to be clear about: the public, append-only transparency log that makes our counters verifiable identifies reactions only by rotating pseudonyms. It never contains your provider, your provider id, your account identifier, or anything others could link back to you, and entries from different periods cannot even be linked to each other without a secret key that only our backend holds and never publishes. Being straight about the other half of that: within a single period, the entries carrying one pseudonym are visibly the same pseudonym, and each entry records when it was added, rounded to the minute. That much is inherent to a log anyone can recount from scratch, and it is exactly why the pseudonym rotates and why the time is coarse. Deletion reverses every one of your entries by appending public revocation entries (that is exactly how the counters are decremented), but the pseudonymous entries and their revocations then remain part of the permanent public record: the log is published, cryptographically anchored, and independently mirrored precisely so that no one, including us, can rewrite it. In other words, deletion removes you; it does not, and by design cannot, rewrite history that no longer references you.
One narrow exception: if we have terminated your account for violating the Acceptable Use Policy, deleting it does not lift the termination. Your reaction records and device signals are still erased as above, but we retain the one-way keyed hash of your provider id (never the id itself) and the fact that the account was terminated, solely to enforce the termination and prevent ban evasion. This is the one case where a deleted account leaves a residual record.
Because we don't store the raw provider id, only its keyed hash, the database lists no accounts at any provider and cannot be turned into a list of them. A copy of it on its own cannot even be tested against a guessed provider account, because the key that produces the hash is held outside it. We hold that key, so we can compute the hash for a provider account you name and see whether an Emojery account exists — which is how an access or deletion request is matched when you are not signed in.
In addition to deletion, you have the rights of access, rectification, restriction, portability, and objection over the limited data we hold. Because we don't retain raw identifiers, an access request typically resolves to a confirmation that the hash of the address you give us is (or is not) on file, along with the reactions associated with it. If you believe we are processing your data unlawfully, you have the right to lodge a complaint with your local data protection supervisory authority. California residents have additional rights under the CCPA, including the right to know, the right to delete, and the right to opt out of sale or sharing. We do not sell or share personal information for cross-context behavioral advertising and never have.
Canada
The operator is established in British Columbia, so Canadian law applies to this processing directly and not only through the regimes named above: PIPEDA federally, and the province's Personal Information Protection Act. Under both you can ask what we hold about you, ask for it to be corrected, and withdraw consent — the same rights this page already grants everyone, exercised the same way. Complaints go to the Office of the Privacy Commissioner of Canada, or to the Office of the Information and Privacy Commissioner for British Columbia, and neither requires you to raise the matter with us first.
One consequence of storing the database in the EU or the US region assigned at sign-in (see International data transfers): while data sits in another country it is subject to that country's law, including access by its authorities under it. What such access could and could not reach is set out in Law-enforcement and government requests.
If we refuse a request
A denial is almost always one of two things: the address you authenticated with has no record on file, or the request asks us to rewrite the append-only log. Where we deny a rights request in whole or in part, we say which of the two it is and why. You can appeal that answer once, by replying on the same issue or email thread within 60 days, and we will answer with reasons. Be clear about what an appeal here buys: there is one person behind this project, so it is a second look rather than a second reviewer. Several US state privacy laws require an appeal route to exist; this is ours.
Escalating instead is always open to you and never needs our permission: your local supervisory authority in the EEA, the ICO in the UK, the FDPIC in Switzerland, the OPC or the BC OIPC in Canada, the California Attorney General, or the equivalent regulator where you live. You do not have to appeal to us first.
Acceptable use
The rules that apply to signed-in accounts and to API callers (one account per person, no automation, no circumvention of anti-abuse measures, no reactions on illegal targets) live on the acceptable use policy page.
Children
Emojery is not directed at children under 13, nor under the higher age of digital consent where one applies — 14, 15 or 16, depending on the EU member state. We do not knowingly collect data from anyone below the age that applies to them, and there is little to collect in the first place: reading counts needs no account. If a child signed in anyway, the account can be deleted from the popup's Account tab without contacting anyone, or you can tell us through the privacy request template and we will delete it.
Contact
Emojery is run as an independent project by a single individual established in British Columbia, Canada, who is the data controller for the processing described on this page. That is the whole organization: no company behind it, no group of entities, no third party deciding what happens to your data. The legal name and a postal address are provided on request, and to any supervisory or privacy authority that asks for them.
For privacy questions or formal requests under GDPR, the UK GDPR, the CCPA, or similar regimes, write to [email protected], open an issue on GitHub, or use the extension's Report tab and include the word "privacy" in the message. All three reach the same person; there is no separate legal department to escalate to. Non-privacy channels are listed on Contact.
Changes
We may revise this policy from time to time. The "Last updated" date at the top of this page reflects the most recent change. If a change materially affects what we collect, how we use it, or who processes it, we will surface a notice in the extension settings on next launch. Your continued use of the extension after that point counts as acceptance of the revised policy; if you disagree, you can delete your account from the popup's Account tab.