Product Updates

Changelog

Selected shipped updates, newest first. Older entries describe the release at that time; the current documentation and policies take precedence.

October 2026 20 updates

Our server moved to Cloudflare

maskbreak.com and the API now run on Cloudflare (Containers, in Eastern North America, next to our database); they ran on Railway until today. Nothing changes in the API. Answers that read the database are faster, and a deploy no longer interrupts anything: a new server is started and checked before it takes over, and the old one finishes what it was doing. The sub-processor list and the privacy notice say so.

Check your page from the dashboard

The dashboard’s setup screen can now check the page with your form for you. Enter its address under step 1 and a browser in the cloud opens it once, as a new visitor would, and tells you what is missing: the script line, a cookie or consent tool that holds the script back, the network or browser part, the sources your Content-Security-Policy needs (each in the directive your policy already uses, ready to copy), a form without the class monocle-enriched, or the site ID on the script tag. It does not send your form and cannot see your server, so step 3 still needs one real form submission. Neither the address nor the result is kept. The privacy notice and the sub-processor list say so.

OAuth resource metadata follows RFC 9728

The protected resource metadata at /.well-known/oauth-protected-resource named https://maskbreak.com/v1 as its resource, which RFC 9728 does not allow at that address, so strict OAuth clients (the MCP SDKs among them) refused it. That address now describes https://maskbreak.com, and the API and the MCP server each have their own document: /.well-known/oauth-protected-resource/v1 and /.well-known/oauth-protected-resource/mcp. Tokens, keys and /oauth/token are unchanged.

The database moved to Cloudflare

Our primary database is now Cloudflare D1, in the United States (Eastern North America), which our server reaches only through a Worker; it was Turso. Every row was copied and checked table by table, and the few written during the switch were carried over. Nothing changes in the API: the same fields, the same decisions, and customer calls stay about as fast, because each one's API key and pins are kept in the server's memory and dropped the moment they change. Turso’s copy was deleted with our account the same night. The sub-processor list and the privacy notice say so.

A used-up month no longer takes your form offline in enforce mode

When a month’s visitor checks are used up, /v1/evaluate answers HTTP 429 with the code monthly_quota_exceeded until the 1st (00:00 UTC). In enforce mode, the integration code we hand out held every submission then (with HTTP 503), so a used-up month, or a bot flood that used it up, took the protected form offline until the reset. The setup code in the dashboard, the integration guide, the API quickstart, the guard on integrations, the examples on VPN detection, the Cloudflare Workers example and the blog guides whose examples held every failed check now let the action through unchecked on that answer and write their usual log line, as watch mode does. Every other error still holds the action, and the promo-code guide still holds the discount (the order can go ahead at full price). The SDK readmes follow with their next release. If your enforce-mode code holds the action on every failed check, add the same branch: on HTTP 429 with the code monthly_quota_exceeded, log it and continue. The log line of the integration guide and the quickstart now also carries the HTTP status: 401 means MASKBREAK_API_KEY is empty or wrong where your form runs. The API itself is unchanged, and the account owner still gets an email at about 80% and 100% of the month.

Accounts from before October keep their allowance until 30 November

Accounts created before 1 October 2026 keep the allowance they signed up with, 1,000 visitor checks an hour with no monthly cap, until 30 November 2026 (it was 31 October). From 1 December 2026 they follow the Free plan’s monthly allowance, 10,000 visitor checks a month, unless they choose a paid plan. grandfathered_until on /v1/usage now reads the end of 30 November. The Terms (Section 4), pricing and the API reference say so. Nothing changes for other accounts.

Account network: which of your accounts share a device or an address

When you send your own accountId with a live key, /v1/evaluate now returns an account object: how many devices this account used in the last 24 hours and 90 days, how many of your accounts this device and this address carried in the last 24 hours, whether this is a new device for an account checked before, and how many of your other accounts it shares a device or an address with. Four reasons come with it: account_new_device, account_many_devices and ip_many_accounts inform only, while device_many_accounts (three or more of your accounts on one device within 24 hours) raises an allow to review, never to a block. That one changes a decision your integration used to receive, so read it before you rely on an allow at signup; a device_sharing rule on the Rules tab relaxes or tightens it, and the other three have rules of their own. Addresses that thousands of strangers share (VPNs, proxies, datacenters, Tor, Apple’s relay, mobile carriers) never link accounts. Everything stays inside your account; we keep a keyed hash of each account ID and an encrypted copy your console shows, both deleted 90 days after the account was last checked (reason codes, privacy).

DPA 1.13 and security whitepaper 2.5

The DPA (version 1.13) and the security whitepaper (version 2.5) now describe the account network (an account ID you send is also kept encrypted, so your console can show which of your accounts are linked), the nightly backups, which moved to Cloudflare R2 in the EU on 17 October, and the console’s new email and phone check, whose provider DPA Annex C now lists. That provider started processing on 18 October, the day it was added to the sub-processor list, without the 30 days’ notice the DPA describes: the check runs only when you type an email address or a phone number into it, and you can still object within 30 days (support@maskbreak.com). The PDF copies were exported again.

Antidetect browsers in the browser-consistency beta

For accounts that turned on the GPU beta and send browserEvidence, /v1/evaluate now raises an allow to review, never to a block, for three new reasons: gpu_inconsistent (the browser’s own WebGL report names a GPU it cannot have), antidetect_randomization (one account showing two canvas fingerprints from two browsers on the same machine type; needs accountId) and antidetect_profile_burst (five or more new browsers on one machine type within a day, each with its own canvas fingerprint). Identical real machines show the same fingerprint, so two identical laptops, or a browser whose fingerprint ID changed, are not flagged. The browser_consistency block adds measurements, hardware_profiles and machine_profiles; for the last two reasons, keyed hashes are kept for 30 days, for your account only (reason codes).

Webhook signing secret can be replaced

Next to your webhook URL in the dashboard, Replace secret creates a new signing secret, and deliveries are signed with it at once. Before, the secret never changed, even when the webhook was removed and set up again. Removing a webhook now drops its secret, so one set up again gets a new one. Replace it whenever someone who saw it should no longer be able to sign alerts, and update your receiver right after (verifying deliveries).

Checks with only a browser check ID are counted

A /v1/evaluate call that sends a browser check ID but no network token now counts toward your monthly allowance and appears in Events, like every other check (Terms, section 4). Such a call returns the device answer, still marked degraded for the missing network part. A call where neither part answered stays uncounted and unstored, as before.

Fixes from our October security review

Removing a team member now replaces the test key they could see and cancels pending invitations to or from them, and an invitation stops working once its sender is no longer an admin. A Google or GitHub sign-in that was linked to an account by its email address can no longer confirm sensitive changes (key rotation, 2FA, email, deletion) on an account without a password: sign in the way the account was created. A smaller plan cannot be chosen while this month’s use is already past it. We also closed a way to fake a public outage on the status page, an open redirect on the IP lookup page, and a caching gap in versioned dashboard files.

Dashboard sign-in kept in a secure cookie

Your dashboard session now lives in a cookie that scripts on our pages cannot read (HttpOnly, SameSite=Strict), and it is accepted only on the dashboard’s own requests. You stay signed in: an open tab moves over by itself. The cookie policy lists the two cookies.

Threat feed no longer reports the account count

The public /api/threat-feed answer no longer carries total_users, the number of Maskbreak accounts. No page showed it, and it is not a figure we publish. The traffic and coverage figures are unchanged.

Legal pages brought up to date

We checked every policy page against what the service does today. DPA version 1.12 and security whitepaper version 2.4 no longer list Auth0 (its tenant was deleted on 6 October) or describe the removed Widgo chat as running, say that the strict Content-Security-Policy on the console is enforced (since 6 October) and that rate limits apply per account, and the whitepaper’s sub-processor summary adds Stripe. The Terms of Service (an 11 October clarification), Privacy Policy, Cookie Policy, sub-processor list and service level objectives correct statements of fact: for example, closing an account cancels a paid plan at once, starting a paid plan replaces an individually agreed quota unless we agree otherwise in writing, address lookups are stored like evaluations, and the daily backup-retention audit first passed on 10 October. The responsible-disclosure policy now says plainly that Maskbreak runs no bug bounty and gives no payment, merchandise or other reward for reports. No sub-processor was added and no customer obligation changed.

Apple’s iCloud Private Relay now asks for review

A decision change, with one new field. When Maskbreak’s network intelligence recognises a visit as coming through Apple’s iCloud Private Relay, /v1/evaluate now returns review instead of block. The relay hides the real address of many iPhone, iPad and Mac users, so a block there could stop ordinary visitors. The visit carries the reason privacy_relay in place of proxy_detected and adds 35 to risk_score (a VPN’s weight) instead of 50. network.proxy stays true, and the new network.privacy_relay, present on every evaluation, is true for it. isSuspicious stays true, and the event reaches your threat webhook with threat_type “Privacy relay” (a relay visit blocked for another reason carries that reason) and a new privacy_relay field in details. The relay never blocks on its own: together with Tor, automation, an emulator or a tampered browser the visit is still blocked, and every other proxy still blocks. A Proxy rule set to Allow in the Rules tab still allows the relay, as before. Set to Review or Block, it no longer applies to the relay, which has no rule of its own (like a virtual machine) and keeps its review when a rule relaxes another signal on the same visit. The rules backtest counts it the same way, relay visits stored before today included. Events stored before today keep their decision. If you route review to an extra check, relay visitors now get that check. The homepage live check and IP lookup already answered Review for the relay. This is a one-off exception to our additive-only stability policy, made so that relay users are not blocked: for relay visits only, proxy_detected becomes privacy_relay and block becomes review; nothing else in /v1 changes. See how the decision is made.

API reference corrections

The documentation now says what the API does. OAuth access tokens are bound to the key they were minted with (since 24 September): after a rotation they keep working through the previous key’s 24-hour grace, and revoking that key, a second rotation or rotating the test key ends them at once with 401, so mint a new token on a 401. During a rotation grace both keys share one hourly allowance. isSuspicious is also true for a Tor exit. total_evaluations counts lookups too. MCP lookup_ip calls use the lookup allowance, not the visitor checks. The per-address ceiling is 200,000 requests an hour. The IP allowlist lives in Settings → API keys → Allowed server addresses. No behaviour changed.

Sentinel.collect() no longer waits for ever

In the browser script at /assets/sentinel.js, Sentinel.collect() and Sentinel.ready() now wait at most 5 seconds for the device check, then return what they have: fingerprintEventId is null when the check has not finished. Before, a device request that neither answered nor failed (a stalled connection) held your submit handler until the browser gave up. The check keeps running and still fills your protected forms when it finishes. Pass collect({ timeout: 2000 }) to change the wait (milliseconds). The integration guide and the API reference now list the Content-Security-Policy sources the script needs.

Sign-in by emailed link is retired

“Email me a sign-in link” is gone from the sign-in and sign-up pages, and the Auth0 integration behind it was removed. Accounts created with it keep their data, API keys and settings. To sign in, use Google, GitHub or a passkey for the same address, or choose Forgot password on the sign-in page to set a password: the code goes to the address on the account. Password, Google, GitHub and passkey sign-in, two-factor authentication and the API are unchanged.

The browser script now gives client-rendered apps a network token

The script at /assets/sentinel.js now keeps one hidden form of its own on the page. Before, Sentinel.collect() returned token: null on a page with no form marked monocle-enriched, and for a form your app rendered after the page had loaded, so a React, Next.js or Vue app sent no network token. It now gets one with no change to your code. The form is never submitted, does not start the device check and stays hidden even when a site styles form { display: block } or sets a strict style-src. It is a form element with data-sentinel-net, so if your own tests select a bare form, use form:not([data-sentinel-net]). Nothing else in the script changed.
September 2026 40 updates

Paid plans, and a monthly allowance on every plan

Maskbreak now has paid plans. Every plan counts visitor checks (/v1/evaluate calls, SDK calls included) per calendar month in UTC, resetting on the 1st, with an hourly cap as abuse protection: Free, 10,000 a month and up to 1,000 an hour, no credit card; Starter, €29 a month (€290 a year), 50,000 a month and up to 5,000 an hour; Growth, €99 a month (€990 a year), 250,000 and 20,000; Scale, €299 a month (€2,990 a year), 1,000,000 and 50,000; Enterprise from €990 a month with custom volume, an SLA and a signed DPA. Prices exclude VAT. Billing and invoices are handled by Stripe, and a subscription can be cancelled from the console’s billing portal, effective at the end of the paid period. /v1/lookup and the MCP lookup_ip tool have their own monthly allowance of ten times the plan’s checks (100,000 on Free); the fixed test_* tokens and the sandbox key are never counted, while test-key calls and console checks run the full detection and count toward the month. Two additive API changes: when a monthly allowance is used up the API answers 429 with "code": "monthly_quota_exceeded" and a Retry-After that runs to 00:00 UTC on the 1st (there are no automatic overage charges, and the account owner gets an email at about 80% and at 100%), and /v1/usage gains plan, monthly_limit, month_used, monthly_lookup_limit, month_lookups_used, month_resets_at and grandfathered_until. Existing accounts: an account created before 1 October 2026 keeps 1,000 checks an hour with no monthly cap until 31 October 2026, and the Free plan’s monthly allowance applies to it from 1 November 2026; individually agreed quotas are kept. Public-interest access is unchanged. The Terms of Service (Sections 4 to 6), the Privacy Policy, the Cookie Policy and the sub-processor list were updated the same day. See pricing and rate limits.

A virtual machine now asks for review

A decision change, not a new field. When the browser check finds that the visitor’s browser runs inside a virtual machine (device.virtual_machine: true), /v1/evaluate now returns review instead of allow. Until today the virtual_machine reason was reported and added 15 to risk_score, but the decision stayed allow and the score was capped at 15; now the visit counts as a threat like a VPN on its own: isSuspicious is true, the score is no longer capped, and the event reaches your threat webhook with threat_type “Virtual machine”. The webhook’s details carry a new virtual_machine field; its tampering field means a tampered browser or an emulator, never a virtual machine. A virtual machine alone never blocks, and every block signal is unchanged. It has no rule of its own in the Rules tab, so a rule for another signal (a VPN set to allow, say) leaves its review standing; the rules backtest counts it the same way. If you route review to an extra check, visitors on virtual machines now get that check. The homepage live check says “Virtual machine detected” and answers Review too. See how the decision is made.

The live check no longer waits 20 seconds for a network check that has gone quiet

When the network check’s script loaded but never answered, the live check on the homepage and on IP lookup kept saying “Still checking” for 16 to 30 seconds before it settled on the address lists. It now asks for the address lists three seconds after the script loaded and shows the answer within about six seconds, saying that the network check did not run; if the network check answers later, the result updates in place. On Safari the second way to run the network check also starts at that point, so most of those visits get the full answer in a few seconds. “Slow connection” is still shown only when the connection really is slow.

A token sent with the wrong Content-Type is read

/v1/evaluate used to ignore a body it could not parse as application/json, so an integration that sent JSON as text/plain (what fetch() sends for a string body without a header), as form data or with no Content-Type got the degraded no-token allow for every visitor. A JSON object is now read whatever the Content-Type, and a form body (token=…&fingerprintEventId=…) gives those fields. If your integration was affected, you will now see real review and block decisions, and those calls are stored and counted like any other. The Bearer scheme is also accepted in any letter case. The live check on the homepage no longer ends on “Inconclusive”: it shows the answer the API gives for the same evidence and says which checks could not run.

Tokens follow your IP allowlist; every limit says when to retry

A security tightening. A live key sent to /oauth/token from an address outside its IP allowlist now gets 400 unauthorized_client and no token; before, a token could be minted anywhere and was refused only when it was used from outside the list. The test key stays exempt, and /v1/usage is unchanged: it still does not apply the allowlist. A 429 from /oauth/token now carries Retry-After: 60, as do the limits on sign-in, signup and the site’s forms. See auth.md and the API docs.

Each answer says how good its evidence was

/v1/evaluate answers from the live pipeline (live keys and your personal test key) carry four new informational fields: network.complete (false for a partial network reading or none), network.sdk_blocked (a token arrived, but the network check could not measure the visitor), device_evidence ("ok", "unavailable" or "not_sent") and evidence (network_age_s, device_age_s and device_replayed, with only what is known). None of them changes decision: if you want thin or old evidence to hold a sensitive action, check them yourself. Test tokens, the sandbox and samples do not carry them. The legacy details object no longer includes id and sid, two undocumented internal identifiers of the network check; every documented field is unchanged. For the age of the network reading, read evidence.network_age_s rather than details.ts. See the response fields. Only the five documented test tokens (test_clean, test_vpn, test_proxy, test_datacenter, test_tor) are test tokens; other strings such as constructor now go to the live pipeline like any other token (the sandbox answers 400).

Legal pages corrected: where data is processed, backups, notices

The DPA (version 1.11), sub-processor list, privacy and cookie policies, terms, security whitepaper (version 2.3) and trust page were corrected. Our application hosting and primary database are in the United States (US East), not the EU as DPA Annex C said; backups stay in the EU (Stockholm). EU-only processing is not offered, so the pricing, public-interest and government pages no longer offer custom data residency. The nightly backup job runs on GitHub Actions and reads the full database, and GitHub is now listed for it; GitHub Sign-In and the emailed sign-in link are live and listed as such. The sub-processor list gains a Region column and a fuller description of our network- and device-intelligence providers, including their possible own use of signals under their terms. Sub-processor change notices are given by a dated entry in the change log on the sub-processor list, at least 30 days before a new sub-processor that processes customer data is added. The terms and DPA also add two customer obligations (no use of the service as the basis of credit, employment, tenancy, insurance or similar decisions about a person unless the law allows it, and deciding on end-user consent for the browser SDK’s device storage); for existing accounts they apply only 14 days after we email the account owner about them. Stored IP addresses in evaluation records are replaced with a keyed, per-customer hash after 7 days; older unkeyed hashes are re-keyed. Customers get a list of the storage the browser SDK uses on their site in the integration guide. Changes that reached the privacy notices earlier without an entry here: Widgo chat loading by itself (22 September), PostHog analytics and session recordings (23 September), and Sentry server error reports, 30-day console sessions and Google One Tap on the log-in page (24 September).

A key that could not be checked is no longer called invalid

When our account store does not answer, /v1/evaluate, /v1/lookup and /v1/usage now return 503 with code: "storage_unavailable" and Retry-After: 30, instead of 401 Invalid API Key. A key that matches no account is still 401. Nothing is let through: retry after the delay and apply your outage policy meanwhile. /oauth/token answers 503 temporarily_unavailable in the same case, and sign-in says it is temporarily unavailable rather than “too many attempts”. This is additive: see error codes.

A rule now changes only its own signal

A Rules-tab rule used to replace the whole decision whenever its signal fired, so a rule such as Multi-accounting → Review could turn a visit that was blocked for a proxy into review. Now a rule speaks only for the signal it names: a proxy, Tor exit, automation, fake browser or emulator that no rule covers still blocks, and a VPN, disposable email or time-zone mismatch still asks for review. To lower a block, set a rule on the signal that caused it. The rule backtest counts changes the same way. decision_source, rule_matched and engine_decision are unchanged.

Your own console checks are test rows

“Check my visit now” and “Test with my browser” store your visit as a TEST event, as the card promised: it no longer counts toward usage or the Overview’s flagged figure, and never sends your webhook or the first-threat email. The Overview’s headline, captions and chart dates now also read in German and Estonian.

Shared result links retired; no country clutter

Old maskbreak.com/result links, which anyone could create without signing in, now open the live check on the homepage, and the API behind them answers 410 Gone; stored results still expire after seven days. The homepage check shows your address without a country flag and draws letter chips instead of icons fetched from a third-party service. The VPN detection page drops its per-country notes: detection reads the connection and the browser, not the country.

Paper and a serif, everywhere

Later the same evening the homepage left the night stage described below: warm paper, ink text, one ultramarine accent and serif headings, with the live check of your visit in a tray under the headline. The three example cards quote real response fields — a VPN alone is review, a tampered browser is block. Pricing, docs, comparisons, industries, playbooks, the blog and the legal pages share it, and so does the console, which adds a short legend for Allow, Review and Block and one line under each Overview figure.

Events on phones, stored reasons, quieter polling

On a phone the Events tab now shows each visit as a card — address and country, the verdict stamp, time and client, one sentence on why, and every signal that fired — instead of a three-column table. Every new event stores the API’s own reasons (and the engine’s verdict when a rule changed it), and the event page reads them back rather than rebuilding the sentence from flags; the events feed returns both fields additively. The console’s refresh polls now cost nothing when nothing changed (a 304), and a hidden tab stops polling until you return.

A night homepage, built around your own check

The homepage opens on a night stage: a faint grid, an ultramarine glow, large type, and the live check of your visit drawn as a dark instrument with monospace labels — the same night/paper pairing the console uses. Nothing decorative stands in for data; the hero object is the real report of the connection and browser you are using. The coverage band and the closing card are night too; the explanations in between stay on paper. Same copy in English, German and Estonian, same checks, same privacy.

Status page incidents need two failed checks

The status page had logged 198 incidents in twelve days, 184 of them two-minute entries from a single failed one-minute probe, and one database blip cascaded into four or five of them. An incident now opens only when two consecutive checks fail, dated from the first; one failed check shows the component as degraded without an entry. A dependent service whose only problem is the database says so. The dashboard check reads the console's settings page, because the dashboard route is answered by an edge challenge that had kept that row Unknown since 8 September. An incident from an independent check that is later switched off closes after a day as unconfirmed, and the entry says so rather than claiming a recovery. Entries from before this change that closed within one check interval are no longer listed, because the current rule would not have opened them; the page says so.

Account emails redrawn

Every email Maskbreak sends — verification and reset codes, the welcome and getting-started notes, security notices, rate-limit warnings, team invitations, the monthly summary, the Fraud Brief and the two form receipts — now shares one design that matches the site: a white sheet on a pale canvas, the logo and a label saying what kind of email it is, ultramarine for links and the one button, and a night panel for the thing you came for, the six-digit code or the snippet to paste. The plain-text alternative is unchanged, no email carries a live API key, and unsubscribe links stay on the getting-started and summary mails only.

A new account starts by checking its own visit

The Integration tab of a fresh account used to open on installation steps before anyone had seen what Maskbreak answers. It now opens with one sentence on what the product does and a “Check my visit now” button: the console checks the connection and browser you are using at that moment and explains the answer in words — what the address is, what was found, what the browser check saw and what your app would do with an allow, review or block. The result is labelled as your own visit, not a connected website, and appears in Events marked TEST. The installation steps follow, and the first one now asks which form to protect first instead of listing every option at once.

The homepage check no longer flashes an interim verdict

On phones and proxied connections the live check could show “Routing inconsistency” or “Inconclusive” for about two seconds before the real VPN or proxy result. A route mismatch seen only on the first, partial browser token is now held as “Checking” until the refreshed token settles it, and a refresh in flight keeps the previous result on screen instead of repainting the limited-scan state.

A location map worth opening

The event page’s “Visitor and location” map is now a real vector map: the request’s country is tinted and pinned, its neighbours give it context, and the view centres on the country rather than on a bounding box that could span Alaska and Hawaii. It is drawn with the open-source jsVectorMap library, self-hosted and loaded only when the panel opens: no map tiles, no third-party geocoding, nothing leaves the console.

Chat is always there on public pages

The website chat now loads by itself on every public marketing page once the page has finished loading, with no notice to click through and no email fallback; pages published after the old reviewed-path list had been getting the email link instead. It still does not load on sign-in, account or result pages, and a browser sending Global Privacy Control gets a plain “Chat” button that loads it only when pressed. Later the same day: the chat no longer pops open on its own on desktop; a fresh visitor sees the launcher, and the panel opens when they open it and then follows them across pages. The privacy, cookie and sub-processor notices describe the change.

Two antidetect browser guides

Should you block antidetect browsers or send them to review? sets out a base policy for the signal, where honest false alarms come from and how to measure a decision before tightening it. Why do antidetect browsers and proxies still give each other away? walks through the places a spoofed browser and its proxy slot contradict each other. Neither claims a detection rate.

Console redesign: one light workspace on the brand’s night

The sidebar and window are the same night surface as the marketing site, with the workspace as one light sheet inside it. Events keeps its compact rows but reads them differently: decisions are Allow, Review and Block pills, findings are tags, and review and block rows carry a coloured edge. The event page puts the recommendation in its own card tinted by its decision; Overview leads with the period’s headline on a night panel and larger figures. Settings, Members and Security inherit all of it. Nothing under 13px, and the German labels still fit a 320px phone.

Practical detection guides

Four guides written for teams putting checks into production: how to test antidetect browser detection with real profiles and an explicit “unavailable” result, what JavaScript alone can and cannot tell you about a VPN, VPN detection without blocking legitimate customers, and stopping credential stuffing through residential proxies. The homepage was refreshed at the same time.

Customer-only device history and optional GPU research beta

Events now has a Device history panel with distinct verified visits, returning devices and account counts for your workspace over 90 days. Repeated submissions count once; historical events are not backfilled. The integration guide also introduces a separate, administrator-enabled WebGPU experiment. It is off by default, requires explicit collection and any necessary visitor consent, and never changes a fraud decision or automatically links identities. Disabling it deletes its saved GPU samples and challenges.

Resource pages checked against the service

Integration guidance now distinguishes review, unavailable and complete allow responses. IP lookup no longer requires an email or subscribes you to the newsletter, handles failed checks explicitly and protects CSV cells from spreadsheet formulas. Status and service objectives explain what the probes actually measure, including gaps and shared dependencies.

Sharper film, quieter visitor report

The 18-second homepage walkthrough is rendered at 2560 × 1600 with less compression in English, German and Estonian. The first-paint loader uses stable evidence rows, a slate-and-blue palette and one small activity indicator. Reduced motion stops that indicator; the film stays deferred until needed.

Simpler console and a Workers integration guide

New accounts start in English; explicit console language choices are remembered per account. Overview and Integration have clearer empty states and setup steps. A Cloudflare Workers route guard includes downloadable source, configuration and tests; it requires your own route, secret and origin-access configuration.

Account-abuse safeguards and clearer privacy notices

Shared database-backed account-attempt limits and email-send budgets strengthen abuse controls. Advertising measurement was removed; Google sign-in is separate and unchanged. Privacy, cookies and sub-processor notices describe current storage, while backup expiry and restore-erasure assurance remain explicitly open verification items.

The homepage, smoother

The navigation pill frosts once the page scrolls under it, a ticker under the hero lists the VPNs, proxies, cloud hosts, fake browsers and bot tools the verdict sees through, dividers draw in as you reach them, the layer cards light up under the pointer and as they pass the centre of the screen, the code window has a Copy button, and the scanner’s loading skeleton dissolves into the result instead of crossfading through it. Nothing on the page is set under 11px any more, and the scanner speaks German and Estonian on /de and /et.

A note after one quiet hour

Sign up, make no API call in your first hour, and one short email arrives: the silence is normal, the curl on the Integration tab already carries your key, reply if unsure. Sent once per account and never again from that template, never with a live key in the mail.

The site in three languages

The homepage, pricing, contact and the API reference render in English, German and Estonian at /de and /et; the blog and resources pages carry translated chrome around English articles; and the console — dashboard, settings, security, members — translates itself the moment you switch language. The EN / DE / ET switcher remembers your choice everywhere.

Public interest: the cap comes off

Hospitals, public health, government, election offices, emergency services, universities and the non-profits that fight abuse get the full API with the hourly limit removed. Free, no expiry, no strings beyond an acceptable-use line. Apply at /public-interest; institutional email domains are fast-tracked, and if you are under attack right now the cap comes off your existing key first. Two new guides on the blog: the program itself, and protecting sign-in and checkout endpoints against account takeover.

Live chat, loaded only when you click

A chat pill on every page. Nothing from the chat provider is fetched until you click it, so no chat-provider request is made before that interaction; if a content blocker stops it, the pill says so and points to email instead.

Sign-up, log-in and password reset, remade

One centred card and one stylesheet for all three, Google first, no checkboxes — continuing accepts the service terms, not optional marketing or device-storage consent — the email field focused for you, and a six-cell code box that submits itself when the last digit lands. The buttons no longer follow the cursor.

The sitemap is generated, and retracted claims stay retracted

Public/sitemap.xml is built from the page and blog models: no duplicate URLs, no redirected posts, honest lastmod. Claims removed in August that had crept back through generators — a signal count, a provider attribution, “paid plans”, detection percentages — are gone again at the source, and the seven /stop pages describe their worked models as illustrative instead of headlining invented customer figures.

The IP and ASN pages, the emails and the share cards join the brand

Server-rendered /ip and /asn pages still wore August’s lime nav and footer; the transactional emails and the og.png share card did too. All of them now use the site chrome and the ultramarine accent.

Headlines are no longer hidden before they are read

/pricing started its hero invisible and revealed it on scroll, so the largest text painted three times later than the page. The reveal animations now leave on-screen elements alone, navigation is not delayed for a fade, and the body font is preloaded everywhere.

The blog, remade: 62 posts on one stylesheet

Every post is generated from one content model with build-time cover art, seven pillar guides were rewritten from live lab evidence, thirteen low-value posts were cut behind 301s, and the dating-app fake-profile playbook — the most visited blog URL of the summer, as a 404 — is back as a real post.

Sign in with an emailed link

“Email me a sign-in link” joins Google and GitHub on the sign-in page where it is offered. Auth0 verifies the address; Maskbreak issues its own session, with the same 2FA and suspension checks as every other route. Disclosed on the sub-processor list.

Support console remade

The admin panel became a console sibling: an overview, per-user drawer, delivery and health views, and real support levers — rotate a key with a 24-hour grace period, force logout, disable 2FA, resend the welcome email, delete with typed confirmation.
August 2026 22 updates

The phone menu works on every page family

The open menu is a full-width sheet under the pill on every page; the signup button was dark-on-blue and the first tap covered the header. The dashboard Overview was remade with calm tiles and an honest chart, one tap from Estonian.

Silent degradations now page

Events API failures, transactional-email delivery problems and user-facing error spikes each raise an alert instead of waiting to be noticed.

The homepage says what Maskbreak does — and shows what it tracks

The hero now reads “Fraud hides behind a VPN. We see through it.” and explains in plain words what your site sends and what comes back: allow, review or block. Under it, a coverage strip shows the anonymity intelligence every verdict is scored against — more than 59 million anonymous internet addresses, 540+ known VPN services, 200+ known proxy services, and the live cloud-range index — served by /api/threat-feed as coverage.ip_intel so the figures can be checked. The comparison table gains a “VPN & proxy detection, service named” row. Every claim that Maskbreak names the VPN or proxy now says “when known”, and a VPN on its own is documented as review, not block. The console, pricing, signup and product pages share one vocabulary: fake browser, cloud server, visitor checks.

Console: readable at 13px, one grey, a real phone nav

Nothing on the four console pages renders under 12px any more; body text, table cells and labels are 13px, and the only secondary grey passes AA contrast. Alerts — webhook URL, Send test, signing secret, delivery log — are a card on the Integration tab instead of a drawer. Every event row carries a one-line “why” built from its signals, and Events is the landing tab. On phones the header is logo + Log Out with a four-link strip under it, and the Events table shows Time, IP and Decision without a sideways swipe.

A verdict we did not produce is never billed

/v1/evaluate used to answer a malformed, tampered or empty client token with a billed 200 “allow”, risk score 0, and an ip: unknown row in your Events log. A rejected token is now the documented 400 Invalid token., and a provider outage returns the degraded response without counting against your hourly limit.

Homepage remake on one stylesheet; one accent everywhere

The homepage’s seven stacked inline style layers and four page-only sheets are now a single file, home-2026.css. The lime accent is retired site-wide for ultramarine — marketing pages, auth pages, console, favicon, blog cover art — and every page shares the same header: ink mark, blue call to action. Type moved to Schibsted Grotesk and JetBrains Mono on 26 August; both are self-hosted.

Phones were getting the desktop layout

The remake dropped <meta charset> and <meta name="viewport">, so real phones laid the homepage out at 980px and zoomed to 0.4. Both are back, and a build check now fails if any page loses them. The comparison table fits a 390px screen, and six blog URLs deleted in June — one of them the most-visited blog address of the quarter — now 301 to their successors instead of answering 404.

There is no paid tier — every page now says so

Twelve days after the Growth tier was withdrawn, six surfaces — the API rate-limit table, its 429 text and FAQ, llms.txt, the contact page — were still describing Growth and Enterprise as plans. All of them now say the same thing: free, 1,000 requests an hour, no card. The endpoint that could still lock the withdrawn tier answers 410, and signup ignores a plan field.

The “under 40 ms” latency claim was false

The site said “under 40ms server-side” in 405 places. Our own telemetry showed a median of 125 ms and a p95 of 371 ms — roughly one request in a thousand met the number. Every figure now states what is measured: under 150 ms, with the live numbers on /status. The latency objective on the SLA page was corrected in the same pass.

Four more vendor round-ups, and 39 thin pages folded into their hubs

Alternatives pages for Cloudflare Turnstile, HUMAN, Signifyd and Friendly Captcha. The 30 per-country VPN pages and 9 per-provider hosting pages, which measured 71–90% identical to each other, are now anchored sections on /vpn-detection and /hosting; the old URLs redirect there.

PHP SDK v0.1.2; GET /v1/lookup says no-store

sentinelsup/sdk 0.1.2 is on Packagist. The authenticated lookup endpoint now sends Cache-Control: no-store explicitly instead of relying on a CDN default to keep private results out of shared caches.

SDKs, the MCP server and the OpenAPI spec finished the move to maskbreak.com

The published SDKs default to maskbreak.com. The MCP server reports its real name and version (binary maskbreak-mcp; sentinel-mcp stays as an alias). The OpenAPI spec documented webhook headers the server never sent — X-Sentinel-*, where the real ones are X-Maskbreak-Signature, X-Maskbreak-Timestamp and X-Maskbreak-Event-Id — and omitted OAuth entirely. Both corrected; the docs page already had the right names.

The 24 August homepage redesign was reverted before it reached production

A dark redesign was committed on 24 August and rolled back on 25 August; production never served it. The light homepage stayed, and the three-link nav and OAuth 2.0 section built on top of it were kept. The 29 August remake above is the redesign that shipped.

The Growth tier was withdrawn

The €49/month Growth founding price announced on 16 July is gone. Nobody was ever charged, and no card was ever taken. Current offer: Maskbreak is free during open beta at 1,000 visitor checks an hour per API key, with at least 30 days’ notice before paid changes. The July entry below is left as it was written — this is the correction, not a rewrite of it.

Console: the overview now shows you what needs attention first

Every tile and every row used to carry the same visual weight, which made "is anything wrong right now" a reading exercise rather than a glance. Threats Detected and Threat Rate now sit on a tinted surface, and each event row carries a coloured rail — red for blocked, amber for review — so you can find them by scanning. The numerals deliberately stay in ink: colouring them red inverted the page's scan order when we tried it. Also: a sticky table header, tighter rows, and a visible focus ring on every input.

Device intelligence signals restored

Our device-intelligence provider account was migrated, and between 2 and 5 August the device layer returned no signals — browserTampering, botDetected, emulator, virtualMachine and incognito were absent from /v1/evaluate responses during that window. Network-layer signals (VPN, proxy, Tor, datacenter) and decisions were unaffected throughout. The device layer is verified working again end to end, and the pipeline now runs against the provider's US region. If you gate on device signals specifically, evaluations from that window are worth re-checking.

A marketing analytics tool was added and removed the same day

We trialled Dreamdata, a business-to-business marketing attribution tool, on our public marketing pages. It was live for roughly 30 minutes before we removed it. In that window its account-level component sent page URL, title, canonical URL, referrer and the requesting IP to Dreamdata, used to estimate which organisation a visit came from. Its visitor-level component was gated behind analytics consent that this site does not grant — except for visitors whose browser blocks Google Tag Manager, for whom the gate is invisible and the visitor-level component, including form tracking, would have started normally. It never ran on the console or any signed-in page and received no customer API or evaluation data. It is fully removed: no code, endpoint or CSP entry remains. Also recorded in our dated sub-processor change log.

Homepage rebuilt

New structure rather than a repaint: the claim now stands alone with the live scanner rising into place below it, the three detection layers move past a sticky progress rail, and the integration section became a real code window with a language switcher covering Node, Python, PHP and cURL. Eleven elements that had been shipping permanently invisible — content in the DOM whose reveal animation never fired — are now visible.

OAuth 2.0 client credentials for API access

You can now exchange your account email and API key for a short-lived bearer token at POST /oauth/token using the standard client_credentials grant, and use that token anywhere an API key is accepted. The token carries your account id, never the key itself, so rotating a key immediately invalidates every outstanding token. Discovery metadata is published at /.well-known/oauth-authorization-server and /.well-known/oauth-protected-resource. API keys keep working exactly as before — this is additive.

Markdown for agents: Accept: text/markdown

Any marketing or documentation page will return a clean markdown rendering when a client actually prefers it, so an LLM or agent reading the site gets prose instead of a wall of markup. Negotiated responses are never cached, so browsers always receive HTML.

Agent discovery: API catalog, MCP server card, and skills index

Machine-readable entry points for AI agents evaluating Maskbreak: an RFC 9727 API catalog at /.well-known/api-catalog, an MCP server card, an agent skills index, WebMCP tool declarations on the docs, RFC 8288 Link headers pointing at all of it, and Content Signals in robots.txt stating plainly that this site may be read, cited and used as grounding.

Screen readers could reach a button they could not announce

The assistant widget's container carried aria-hidden while holding a real, focusable close button, so keyboard users could tab to a control no screen reader would read out. The attribute now sits on the decorative bubble only.
July 2026 47 updates

Sitewide friction sweep: docs page restored, honest error states everywhere

A full audit pass across the console, docs, and auth flow. The API reference at /api is reachable again (a routing regression had it redirect-looping). The dashboard now surfaces real error text instead of failing silently (playground, IP-lookup tool, CSV export, rules tab), quota 429s send a real Retry-After, the docs’ copy-paste examples were fixed end-to-end, invite and OTP flows gained honest recovery paths, and the mobile keyboard finally lets you type an IP in the lookup field.

Google Ads measurement returned — cookieless, consent-denied

Historical release: the Google Ads tag returned in storage-denied mode. It was removed on 6 September 2026. Storage-denied pings did not establish a blanket exemption from consent requirements; the current Cookie Policy supersedes this old description.

GET /v1/usage, webhook event IDs with retries, and rule backtesting

New GET /v1/usage returns the calling key’s quota position — key_type, hourly_limit, used_this_hour, remaining, resets_at, plus lifetime total_evaluations and limit_hits. It works for both live and test keys (each reports its own bucket) and the call itself is free — it never consumes quota; the in-window counters are advisory (in-memory, per-process, reset on deploy). Webhook payloads now carry a unique event_id (32-hex, test events included, echoed in an X-Maskbreak-Event-Id header on every delivery), and failed deliveries are retried: up to 3 attempts per event at roughly 1 and 8 minutes, best-effort in-process, with the same event_id on every attempt — so receivers dedupe on event_id instead of guessing from timestamps, and the Events log stays the source of truth. Also today: rules can be backtested in the dashboard — see how a rule would have decided your recent traffic before saving it — the status page’s per-service breakdown gained uptime history, and the antidetect detection guides were rewritten from scratch.

Webhook delivery log, multi-account investigation, and histories across the console

Threat-alert webhooks now keep a rolling 30-day delivery log — event type, HTTP outcome, and any error string, never payloads and never end-user IPs — in the dashboard's Tools drawer, so a silently failing endpoint is diagnosable at a glance. False-positive reports gained a status loop: each report is tracked open → resolved or dismissed, readable back via GET /api/fp-reports, so filing one is no longer a black hole. New GET /api/device-accounts lists devices seen across multiple of your accounts (account count, first/last seen) for multi-account investigation — per-customer and hash-only, as always. Settings adds email preferences (product notes and the monthly usage digest are individually switchable; security notices stay on) and org invite history; the Security page shows the sign-in browser history behind new-browser alerts. The status page's 90-day uptime bar now breaks down per service, /v1/evaluate adds device.first_seen (additive) so a brand-new device is distinguishable from a returning one, and the OpenAPI spec lands at 1.3.0 with the signed-webhooks delivery contract documented as a first-class webhooks section.

Shareable links to any filtered view or single event

The Events view now lives in the URL: filters (range, decision, signal, threats-only, search, visitor) are encoded in the hash as you work, so a refresh keeps your place and the address bar is always a handoff-ready link. Every event's detail panel gains a copy-link button — the link opens that exact event, drawer and all, for any member of your org (backed by an additive ?id= on /api/lookups, still strictly account-scoped). Changing any filter returns you to the full log.

Console refresh + rate-limit headers, request IDs, and a docs catch-up

The Events tab gained an at-a-glance stat strip, decision and signal filters (?decision= / ?signal= on /api/lookups and the CSV export, additive), a one-click Export button, keyboard navigation (rows open with Enter, ↑/↓ steps through events in the detail panel), and honest failure states — a failed load now shows a retry instead of an eternal “Loading…”, and a failed Rules load disables Save so it can never wipe your policy with defaults. Every keyed API response now carries X-RateLimit-Limit / -Remaining / -Reset so you can back off before a 429, plus an X-Request-Id to quote to support. The docs page finally documents GET /v1/lookup/{ip}, the per-account test key, the hosted MCP server, and the exact webhook payload.

Exceptions: pin an IP or visitor to always allow or always block

Alongside signal rules you can now pin a specific IP address or visitor: an explicit “always allow 203.0.113.7” beats a generic “VPN → block.” Pins are managed in the Rules tab or straight from any event's detail panel, apply to /v1/evaluate and /v1/lookup, and report themselves additively — decision_source: "exception" with the matched pins in a new exception_matched field, the engine's own verdict preserved in engine_decision, and webhook deliveries labeled Customer exception (…). Test tokens obey pins too, so one cURL verifies a pin before it ever touches live traffic.

Per-account test keys: the full pipeline with zero footprint

Every account now has its own sk_test_… key (Settings → API Key). Unlike the public sandbox it runs the complete live pipeline — real tokens, device intelligence, your rules and pins included — but events are badged as test in the console, excluded from usage and stats, and never fire webhooks or limit emails. Responses carry "test": true, the key has its own hourly bucket, and it rotates without a password. Safe for CI and staging by construction.

API-key IP allowlist

Restrict live-key calls to your own server addresses (exact IPv4/IPv6 or IPv4 CIDR, canonicalized on save): anything else gets a 403 that names the calling IP in its hint. Enforced on /v1/evaluate, /v1/lookup, and the hosted MCP endpoint; the test key and the console are deliberately exempt, and every allowlist change emails a security notice. Configure it in Settings → API Key Security.

Report false positives from the event drawer

Every event's detail panel now has a “Report false positive” button — one click files the event's full context with our team (deduped per event) so wrong verdicts feed detection tuning instead of a support back-and-forth. Reported IPs follow the same 7-day hashing schedule as evaluation logs, and reports are deleted with your account.

Email you can actually opt out of — and a monthly usage digest

Onboarding emails now carry a real unsubscribe link (RFC 8058 one-click for mail clients, a confirm page for humans — and the link no longer trips corporate mail-scanner prefetch). Suppression is honored at the recipient query, not at send time. New: a monthly summary of your own account's traffic — evaluations, threats, and the signal breakdown — sent only to accounts with real activity, with the same unsubscribe. Security and billing notices remain transactional and unaffected.

Passkeys

Sign in with a passkey (WebAuthn) instead of a password — enrol from the Security page, with re-authentication required to add one and a security notice on every add or removal. Passkey sign-in gets its own rate bucket so it can never lock out password login.

Unified SDK: device + network in one embed

The whole point of Maskbreak is device and network intelligence — but the old client SDK captured only the network token, leaving device signals as a separate manual integration. The new sentinel.js loads both layers from a single <script> and injects both tokens (monocle for network, sentinel_fp for device) into your forms. Call Sentinel.collect() to get { token, fingerprintEventId } and forward both to /v1/evaluate — the endpoint accepts sentinel_fp as an alias, so device+network is now the default integration, not an opt-in. The quickstart, SDK READMEs, and AI-agent guide were all reframed around it; the dashboard’s “Test your browser” now exercises both layers. If a hardened browser blocks the device layer, evaluation continues network-only.

Decision rules: your policy, enforced on the API

A new Rules tab lets you decide what each signal does: set VPN to Review, antidetect browsers to Block, disposable email to Allow — whatever fits your risk appetite. The decision field then returns your action (most-severe rule wins when several match), and your backend routes on it. The engine's own risk verdict is preserved in the additive engine_decision field, with decision_source and rule_matched alongside. Test tokens obey your rules too, so curl … test_vpn verifies a rule before you ship it. Also new: a “Test your browser” button in Events runs a real evaluation of your own connection through the live pipeline and streams the result into the log; the event detail panel gained a self-hosted world map (no third-party map tiles) marking the request's country; and the Overview chart-render bug from the Events-first change is fixed — it no longer blows up when the tab is opened from a background state.

Events is now the console's home — live-updating, with a rebuilt Overview

The console now lands on the Events log: new events stream in automatically every 20 seconds (with a Live indicator, manual refresh, and a highlight on arrivals — no page reloads), visitor IDs are clickable to filter to that visitor, and the detail panel gains a “Back to events” control. The Overview was rebuilt around it: the daily chart now has a fixed height with rounded bars (it previously stretched to match the signal column and dwarfed low-volume accounts), signal composition sits in a compact three-column band — Outcome, Network, and Device side by side — and the old Recent Activity table is gone in favor of the full event log.

Events: an identification log with per-visitor detail

New Events tab in the console: every evaluation your key ran as a row — time, pseudonymous visitor ID, IP + country, browser/OS, signal chips, and the allow/review/block decision — filterable by range, threats-only, IP or visitor search. Click any row for the full picture: visitor history (events, threats, first/last seen, one-click filter to that visitor), the network verdict with service name, the device layer, and a copyable event record. Evaluation rows now persist a coarse browser/OS label, network service, risk score, decision, and a one-way-hashed visitor key (raw device identifiers are still never stored — privacy policy §1 updated). Events without a device layer say exactly how to enable it. The overview's daily chart is also capped at a sane height and the breakdown explains itself when the fingerprint layer hasn't fired yet.

Dashboard: device signals everywhere, geo & time-of-day intelligence, CI tooling on the integration tab

The overview now shows the full signal taxonomy — network (VPN, proxy, datacenter, anonymous) and device (bot/automation, antidetect/tampering, incognito, disposable email) — with 30-day windows and vs-prior-period deltas, plus a fourth Device Flags stat tile. New sections: Geo Intelligence (top countries with per-country threat counts; country is kept as an aggregate while raw IPs still hash out at 7 days), Time of Day (weekday×hour heatmap and hourly clean-vs-threat composition, UTC), and auto-computed insight cards that stay hidden until your sample is large enough to be statistically honest. The API & Integration tab gains a Test & Ship section: the sk_test_sandbox CI recipe, deterministic test tokens, and the official Node/Python SDK installs. Powered by additive aggregates on /api/dashboard-init — nothing about existing fields changed.

Growth founding price, CI sandbox key, stop-fraud playbooks, and a self-serve trust surface

Pricing now shows a concrete middle tier: Growth at €49/month (5,000 req/hr, priority support) — a founding price locked for everyone who signs up during beta, with billing starting only after 30 days' notice when beta ends, and overage always throttled (429) rather than billed. Developers get a public sk_test_sandbox key that answers the deterministic test_* tokens with documented shapes, no account needed — wired for CI. New content surfaces: six /stop playbooks (account takeover, fake signups, card testing, bonus abuse, trial abuse, multi-accounting), a glossary, and live-tracked hosting-provider range pages. Procurement can now self-serve the security whitepaper (PDF included) and the sub-processor list with a dated change log. The homepage gained an honest live-stats band fed by real production counts, and the API docs open with task-based entry points and a freshness stamp.

Trust, privacy, and accuracy documentation pass

A security and compliance review swept every claim on the trust, privacy, and API pages against what the code actually does. We corrected the security-controls descriptions to match reality, documented alert-webhook and newsletter data categories and a 72-hour breach-notification commitment, clarified that arbitrary-IP lookups use network reputation (not the full live-session analysis), documented the API's fail-open behaviour, and tightened two internal data-scoping details. No customer action needed.

Dashboard redesign: honest charts, live quota, alert health

The traffic chart now draws real per-day columns with integer axis labels instead of a smoothed curve that invented shapes at low volume. Stat tiles suppress noisy week-over-week percentages on small samples, the plan card shows your actual hourly quota with a live this-hour meter, an Alerts chip reports whether your webhook is delivering (or failing), one-click Simulate buttons fire the new test tokens from the Playground, burner-email hits are tagged in Recent Activity, and an API-status chip answers "is it me or Maskbreak?" without leaving the console.

Test tokens, email intelligence, and error hints on /v1/evaluate

Deterministic test tokens (test_clean, test_vpn, test_proxy, test_datacenter, test_tor) exercise your allow/review/block handling from a terminal — never billed or stored. Pass an email to get email.disposable back from our 8,000-domain burner feed (adds the disposable_email reason and escalates allow to review). And 401/400 errors now carry hint + docs fields that name the actual mistake.

Real uptime history and an investigable activity log

Uptime probes now persist per-day, so the status page's 90-day bar shows genuine daily percentages with sample counts — days before tracking began render as "no data" instead of invented green. The dashboard's Recent Activity gained IP search, a threats-only filter, and pagination via new /api/lookups query params.

Live scanner got a skeleton loader and a seamless reveal

The homepage Live Risk Assessment now loads as a skeleton preview of the final panel — real row labels with shimmering placeholders exactly where each value lands — so results materialize in place instead of replacing a separate loading screen. The whole handoff is faster and steadier, and honors reduced-motion preferences.

Multi-accounting detection now works through the official SDKs

The Node SDK's evaluate() forwards accountId (it was previously dropped before reaching the API) and its TypeScript definitions gained the device multi-accounting and times-seen fields plus the full reason-code list. The Python SDK accepts account_id.

API reference audited line-by-line against the implementation

Every documented endpoint, field, limit, and error code was re-verified against the live API. Corrections: isSuspicious semantics spelled out (route on decision — Tor and datacenter drive it, not the legacy flag), the real per-IP backstop (50,000/hr) replaces an understated figure, the 403 suspended-account response is documented, two missing reason codes (high_activity_device, multi_account_device) were added everywhere, and the OpenAPI status schema now matches the actual response.

Plan label consistent across the whole console

Settings, Security, and Members now show your actual plan in the sidebar and topbar, matching the dashboard — previously they hardcoded "Free" regardless of the plan on your account.

Dashboard network feed shows real numbers

The "Maskbreak Network" feed on the dashboard now reports genuine 24-hour totals instead of seeded baseline figures, matching the honesty policy the public threat feed already follows. The unused /api/device-seen endpoint was retired (410 Gone).

Scanner score card tints with the verdict

The Live Risk Assessment's score panel now shifts color with the outcome — soft red on threat, amber on routing anomaly, green on clean — so the verdict reads at a glance.

Non-essential tracking removed; legal notices rebuilt

Microsoft Clarity, Google Ads conversion tags, and the third-party blog embed no longer load on public pages. The Cookie and Privacy notices now match actual storage, profiling, retention, complaint, and transfer behaviour; Terms are explicitly business-only and align deletion timelines. The Ads tag returned on 19 July and was removed again on 6 September. See the latest privacy update above.

Blog claims audited and reading tools improved

Unsupported percentage guarantees were replaced with measurable rollout guidance, an unsubstantiated named-network article now redirects to the residential-proxy guide, heading hierarchy was repaired, reading times calculate from the article, and code blocks gained copy controls.

Enterprise conversations get a calendar

The Enterprise plan and contact page offered a direct book-a-15-min-call link alongside the contact form. Removed 16 Aug 2026 — nobody booked through it, so enterprise contact is email again.

Look up any IP — single or bulk — on the free IP Lookup tool

The IP Lookup tool gained single and bulk checks for public IPv4 and IPv6 addresses, with CSV export for up to 20 unique addresses. Coverage depends on the available network feeds and does not include browser evidence. Updated 6 Sep 2026: the original email gate and newsletter enrollment were removed; bulk checks now require no email.

New API endpoint: GET /v1/lookup/{ip}

Programmatic verdicts for arbitrary IPs with your API key — same signal language as /v1/evaluate, shares the per-key 1,000/hour quota, documented in the OpenAPI spec. Lookups appear in your dashboard alongside session evaluations.

Maskbreak MCP server — IP intelligence inside Claude, Cursor, and any MCP client

A Model Context Protocol server (@sentinelsup/mcp) that gives AI assistants two tools: lookup_ip for live fraud verdicts on any IP, and service_status for API health. One-line setup with a free API key — or use the hosted endpoint at https://maskbreak.com/mcp with no install at all.

The Fraud Brief now actually ships monthly

Subscribers get a welcome issue immediately and a monthly digest of the newest research, compiled automatically from the blog. Every email carries a one-click unsubscribe (RFC 8058) and a signed unsubscribe link — no login, no dark patterns.

Fraud Brief capture extended across the whole content library

The monthly Fraud Brief signup now appears on the blog index, every case study, all comparison pages, and the industry landing pages — not just individual blog posts. Same promise as always: one technical email a month on what fraudsters changed, no spam, unsubscribe anytime.

Operational alerting upgrade

The platform now notifies the team immediately when server-side error rates spike or the process hits an unexpected fault, on top of the existing uptime probes on /status. Faster detection, faster fixes.

IP Lookup redesigned with a two-phase scan

The free IP Lookup tool now paints your connection identity (IP, country, browser) instantly and fills deep signals — VPN, proxy, datacenter, Tor, device intelligence — as the full verdict arrives. No more staring at a spinner while everything resolves at once.

Scanner first response now answered at the Cloudflare edge

The homepage scanner's first-pass identity check is now served by an edge worker in roughly 20–60 ms instead of round-tripping to origin. The scanner paints its first result near-instantly on every continent; full verdicts continue through the origin pipeline.

Third parties moved off the homepage critical path

Analytics and session-replay tags now load on idle or first interaction instead of competing with the hero render. Motion CSS deferred the same way. Faster first paint on slow connections, identical behavior after load.

One canonical spelling per URL

Duplicate URL variants (.html suffixes, trailing slashes) now 301-redirect to a single canonical form on every page, consolidating link equity and eliminating duplicate-content ambiguity.

Homepage comparison table expanded from 5 to 11 feature rows

The capability comparison on the homepage now covers antidetect-browser detection, residential-proxy classification, device intelligence, AI-agent detection, latency, free-tier depth, and more — so the differences are visible without leaving the page.

Signups are now screened by Maskbreak itself

New-account creation runs through our own verdict pipeline: per-network signup caps plus server-side anonymizer screening. Maskbreak dogfooding Maskbreak — the same signal set we sell now protects our own front door.

Password changes instantly revoke all previous sessions

Changing or resetting your password now bumps a per-user token epoch, invalidating every previously issued session token immediately — on all devices, with no logout lag.

Cookie banner removed

Historical UI change: the consent banner was removed. Correction, 6 September 2026: denied storage does not by itself remove consent obligations. Advertising measurement is now removed; the current Cookie Policy describes the remaining technologies and their purposes.

Maskbreak goes light — full-site redesign

Every page — homepage, console, docs, blog, case studies, all 95 public pages — converted from the dark editorial theme to a clean light shell with lime accents. New site-wide motion layer, unified pill navigation, an editorial blog reading experience, redesigned case studies with live counting metrics, and Senti, the scanner mascot that reacts to your verdict.

Dashboard reorganized: Overview and API & Integration tabs

The console now splits at-a-glance monitoring (traffic chart, threat log, recent activity) from integration work (API key, playground, webhooks, quick-start). Device-intelligence results are now persisted and shown in dashboard lookups, so past sessions keep their full signal detail.
June 2026 15 updates

Homepage scanner: cleaner, more honest risk presentation

The semicircle risk gauge is gone, replaced by a clear score and bar in a muted enterprise style. A dedicated Device Intel row names the device-layer verdict. The demo tab now shows a genuinely clean profile (score 0) matching what the real API returns for clean traffic — no more misleading red rows on a clean scan.

Response-header hardening

Dropped the X-Powered-By header, added Cross-Origin-Opener-Policy, and de-duplicated CSP origins across all responses.

Live article feed on the blog

New research articles now land on /blog automatically via an embedded publishing feed, alongside the long-form guides. Fresh coverage without waiting for a site deploy.

Cross-browser Hardware ID with sighting counts

The device checker now keys its “times seen” count on a cross-browser Hardware ID instead of the per-browser visitor ID — switching browsers no longer resets the count. The sighting pill turns red past 5 sightings, and the count is surfaced through the API as well.

Carrier-grade NAT no longer triggers a routing-anomaly false positive

Some mobile and broadband ISPs route a single subscriber's traffic to different destinations through different public pool IPs, so our origin and the network engine can legitimately see two different addresses from one clean connection. The scanner previously read this as a routing anomaly (amber 50). It now recognizes the case — both IPs clean and announced by the same network — as carrier NAT and returns a clean result. Rotating residential proxies (different networks, or any datacenter/VPN flag) still score as detected.

Signup rate limiting per network

New accounts are now capped at 10 signups per IP address per 24 hours, throttling automated bulk account creation while leaving plenty of headroom for shared networks (offices, universities, CGNAT carriers).

Removed client-side DevTools and right-click blocking

Dropped the script that blocked F12, view-source, and the context menu. It was trivially bypassed, hurt legitimate developers inspecting the integration, and provided no real protection — the actual fraud detection runs server-side. The console self-XSS warning (“don't paste code here”) is retained.

Eliminated the white flash when navigating between pages

Every page now declares its dark canvas before stylesheets parse, so moving between pages no longer shows a brief white flash. The console-branding script was also deferred so it never blocks first paint.

Fixed stray HTML entities showing in button labels

A handful of buttons set through JavaScript (the API playground “Run Request” button, blog newsletter “Sending…” states, and a few others) were rendering raw entity codes instead of the intended characters. All now show the correct glyphs.

Signup and login pages redesigned with richer left panel and improved UX

Sign-up left panel now shows the Maskbreak logo, a bold new headline, and a 4-point feature checklist (VPN/proxy/Tor detection, browser fingerprinting, 1,000 free evals/day, one-call REST API). A "Free tier included" badge and a perks row were added above the CTA. Login left panel gains three dashboard-access cards (Threat Log, API Keys, Webhooks) below the headline. Primary buttons on both pages updated to brand-accent yellow from white.

Nav links and CTA button standardized across all 77 public pages

Nav items corrected site-wide: Home → Case Studies, API Docs → Docs, Trust → Contact. "Get Started" button simplified to "Get started". Pages with inconsistent active state or missing Contact link (blog.html, trust.html) fixed individually.

4-column footer with crosshair logo SVG deployed across all 89 public pages

Footer replaced site-wide with a canonical 4-column grid (Product / Compare / Use Cases / Company). Footer logo crosshair SVG now renders correctly on all pages. External async CSS files (for-page.css, vs-page.css, case-study.css) that were overriding inline footer overrides have been updated to match the canonical layout.

HTML caching disabled — Cloudflare no longer serves stale pages after a deploy

All HTML responses now carry Cache-Control: private, no-store, no-cache, must-revalidate, max-age=0 plus CDN-specific no-store headers. Previously pages were cached at the Cloudflare edge for 30 minutes (max-age=1800), so nav and footer fixes were invisible to visitors until the CDN TTL expired. Static assets retain their long-lived cache headers.

Device-intelligence reliability upgrade

Migrated our device-intelligence integration to a Cloudflare-backed custom subdomain, with an automatic CDN fallback while DNS propagates. Updated across all pages that load the agent.

Scanner loader can no longer get permanently stuck when both the device SDK and network call fail

showDefaultResult() could route into the first-paint inconclusive branch of showScannerResult() (when __sentinelInconclusiveSeen was still false), showing “Analysing connection…” with a pending circle and then returning early — leaving the panel frozen forever because no subsequent timer would fire. Fixed by setting __sentinelInconclusiveSeen = true inside showDefaultResult() before the scan result call, ensuring it always reaches the second branch (“Network identified”) as a final state.
May 2026 32 updates

Mobile NAT64 false positive: French/EU mobile users no longer flagged as routing anomaly

When a device has a native IPv6 address (CF dual-stack) but the device-intelligence endpoint is IPv4-only, the OS routes through the carrier's NAT64 gateway — creating an apparent IP mismatch that previously triggered routingAnomaly = true (amber 50, ANOMALY on VPN/Proxy row). Common on Orange, SFR, and Bouygues mobile in France. Server now detects the IPv6→IPv4 split and classifies it as mobile dual-stack: uses the IPv4 as the display IP (covered by our intelligence DB), clears the route-mismatch widget, and returns score 0 / CLEAN. Same-version mismatches (IPv4↔IPv4) still flag amber since those are consistent with rotating residential proxies.

Scanner widget: Network Intel grid no longer stuck at “…” on routing anomaly path

The routing anomaly branch in showScannerResult() returned early before calling setDetail(), leaving VPN / Proxy / Datacenter / Tor Exit / Country / Risk Score all frozen on the loading ellipsis. The early return now populates all six fields (CLEAR for network flags, country flag + code, amber 50 for risk score) and calls resolveDeviceFallback() so the Device Intelligence row also fills from server-side UA data.

Scanner mobile overflow: ISP / Service and VPN / Proxy values no longer clipped off-screen

Long IPv6 addresses (38+ chars) caused the scanner widget to expand horizontally beyond the viewport on mobile, pushing the right-side values of ISP/Service and VPN/Proxy rows off-screen. Three CSS fixes: overflow:hidden on .scanner-widget clips any overflow; min-width:0; word-break:break-all; flex-shrink:1 on .result-row-val lets flex items shrink and wrap; align-items:flex-start on .result-row handles multi-line IP values. Route mismatch JS also fixed: replaced <br> inside inline-flex (broken) with a proper column layout, and fixed mojibake ↳ arrow.

Scanner result message: HTML entities rendering as literal text

msg.textContent does not parse HTML entities, so “Verified residential &mdash; you&rsquo;re clean.” and “Analysing connection&hellip;” were displayed verbatim with the entity codes visible. Replaced with actual Unicode characters (em dash, right single quotation mark, ellipsis). ISP/Service logo chip also fixed: generic names (Mobile ISP, Residential ISP, Mismatched route, etc.) no longer render a fallback “M” initial chip — unrecognized brand names are now shown as plain text only.

Mojibake: ▌ cursor character in “How It Works” code blocks

The blinking cursor character ▌ (U+258C, LEFT HALF BLOCK) in the three “How It Works” terminal code snippets was double-encoded as Windows-1252, displaying as ▌ across all browsers. Replaced all three instances with the correct UTF-8 character.

Mobile performance: font weight pruned, content-visibility, preconnect

Three performance improvements targeting mobile first-paint. (1) Dropped Space Grotesk weight 300 from the Google Fonts request — not used in any CSS rule, saves ~8 KB of font transfer on every cold load. (2) Added content-visibility:auto with contain-intrinsic-size to .value-props, .features-section, and .proof-section — browser skips off-screen layout and paint on first render, measurably reducing LCP on long pages. (3) Upgraded flagcdn.com from dns-prefetch to preconnect, eliminating the full DNS + TCP + TLS handshake before the first flag image renders in the scanner.

Mobile menu redesigned: clean dark overlay with chevron links and neutral CTA buttons

The mobile hamburger menu was restyled to match the site’s aesthetic. Navigation links: white text at 1rem / 600 weight with a right-side chevron arrow, replacing the dim uppercase small-caps. CTA row: LOG IN renders as a muted bordered pill, GET STARTED as a solid white / black button — removing the harsh neon lime that clashed with the dark overlay and was flagged as visually inconsistent with the auth page button redesign.

4 new blog posts: card testing, CAPTCHA farms, loyalty fraud, gaming launches

Four production-ready posts shipped to the blog. Card Testing Attacks covers the full bot operation — proxy routing, antidetect browsers, timing randomization, economics ($5–$50 per live card) — and shows exactly why Stripe Radar alone is insufficient. CAPTCHA Farm Economics documents the $0.0005–$0.002/solve market, how reCAPTCHA v3 gets gamed with warmed profiles, and why CAPTCHA is now only a deterrent against the least sophisticated bots. Loyalty Point Fraud maps dark-market valuations ($0.004–$0.012/mile), all four attack vectors, and a Python integration example. Bots at Product Launches breaks down waitlist hoarding, referral self-referral, SaaS trial stacking, and sneaker-drop scalping with real data. All posts include Article + FAQ + BreadcrumbList schema, newsletter capture, and related-article cross-links.

2 new case studies: iGaming bonus abuse + travel scalper bots

Two full case studies added. EU Sportsbook — iGaming Bonus Abuse: professional bonus hunters using Dolphin Anty + Bright Data residential proxies drained €87K in bonus credits before Maskbreak's antidetect detection and device clustering caught the pattern in 48 hours. European OTA — Travel Scalper Bots: Playwright-driven inventory-hoarding bots crashed checkout conversion to 34%; Maskbreak's headless artifact detection, ASN classification, and form-fill timing signals shut down the operation without adding CAPTCHA friction. Case-studies index updated with both cards; aggregate stats updated.

Blog UX: category filter bar + reading time badges + card glow hover

Blog index redesigned with three UX upgrades. A sticky filter bar above the grid lets visitors filter by category (Guide, Research, Case Study, Analysis, Deep Dive, Engineering, Industry) — pure client-side JS reading tag text, zero server round-trips. Reading time badges auto-inject into every card footer via a lookup map (7–13 min estimates). Card hover effect gains a subtle accent glow (box-shadow: 0 0 0 1px rgba(39,51,217,0.12)) alongside the existing lift animation. Article count updated to 34.

Device Intelligence loads immediately — removed 3-second artificial delay

The device-intelligence SDK lazy-loader was wrapped in setTimeout(load, 3000) as a safety throttle. Since loadDeviceIntel already awaits the SDK promise, the timeout just stalled the DI panel for 3 full seconds on every dashboard open — even on fast connections. Changed to load() (immediate). Client-side fetch to /api/device-intel now has AbortSignal.timeout(8000) so the DI panel fails gracefully instead of hanging if the upstream device-intelligence API is slow.

bcrypt async in OAuth flow; guard.js 7-day immutable cache; crypto hot-path fix

Three server-side performance wins. bcrypt: Google OAuth new-user creation used bcrypt.hashSync inside a db callback, synchronously blocking the event loop on every first-time Google login. Replaced with await bcrypt.hash() in an async callback. guard.js: Cache-Control changed from no-store to public, max-age=604800, immutable — saves a round-trip on every page load. crypto: parseUaIntel was calling require('crypto') on every invocation; changed to use the module-level crypto import.

Scanner hardening: defense-in-depth output encoding

Hardening pass on the homepage scanner: every dynamic value rendered into the panel (IP, service name, routing details) now goes through a strict HTML-escaping helper as defense in depth. Also added DNS prefetch hints for the device-intelligence CDN and favicon service to shave ~20ms off first-load.

Session, console, and input-validation hardening; dependencies patched

Four hardening improvements shipped together. Admin console sessions now clear automatically when the tab closes. The 2FA enrollment flow gained stricter state checks. Country-code validation tightened to strict two-letter alpha input. Dependency audit run and patched — npm audit now reports 0 known vulnerabilities.

Blog index updated: 34 posts, JSON-LD refreshed, case-studies aggregate

Blog hero stat updated from 16 → 34 articles reflecting the full post fleet. JSON-LD BlogPosting list includes all new posts. Case-studies/index.html aggregate stat updated to account for the two new case studies. Display-name input is normalized server-side before write.

4 new blog posts: ATO playbook, iGaming bonus abuse, headless detection, agentic AI browsers

Shipped four long-form pieces targeting fresh high-intent keywords. Account Takeover Prevention: The 2026 Engineering Playbook covers session-cookie theft, real-time phishing kits, and device-bound sessions. iGaming Bonus Abuse Detection targets sportsbook/casino multi-account fraud with UKGC/MGA regulatory framing. Headless Browser Detection in 2026 documents what works after stealth plugins kill the classical signals. Detecting Agentic AI Browsers covers ChatGPT Atlas, Claude Computer Use, OpenAI Operator, and the policy decision every team needs to make about AI traffic. Each post ships with Article + FAQ + BreadcrumbList schema and inline links into the existing post graph.

Sitemap, llms.txt, and blog-index refreshed

Added the 4 new posts to sitemap.xml with priority 0.95 and a May lastmod. Bumped homepage, blog index, and changelog lastmod to 2026-05-09 so Google and Bing recrawl. Refreshed /llms.txt with the new posts surfaced for ChatGPT/Claude/Perplexity citation discovery, plus an expanded "Capabilities" block that explicitly names ChatGPT Atlas / Claude Computer Use detection. Updated blog-index BlogPosting JSON-LD list with the new headlines.

Internal linking pass — every new post gets 3 inbound contextual links

The four new posts each link into the existing post graph (residential proxies, antidetect browsers, credential stuffing, multi-accounting, Puppeteer/Playwright, AI takeovers) with relevant anchor text rather than navigation-style "read more". Improves crawl depth into the deeper posts and concentrates topical relevance for the cluster keywords. Reciprocal Related-Articles cards added to each new post pointing back at the cluster.

Newsletter capture on every new blog post

"Fraud Brief" newsletter block injected near the article CTA on all 4 new posts. Inline form posts to /api/newsletter with deduplication, fires generate_lead in GA4 on success. Same pattern as the existing post fleet — consistent capture surface across the blog.

Topical cluster expansion: bot detection, ATO, multi-accounting

The blog now has 30 indexed posts across three reinforced clusters: bot & automation (headless, Puppeteer/Playwright, agentic AI, antidetect, captcha-less), network & identity (residential proxies, VPN evasion and other residential networks, Tor), and platform vertical (iGaming, OAuth signup, ticketing, dating, Stripe, Shopify, fintech, e-commerce, SaaS). Cluster cross-linking is what moves long-tail rankings — each new post strengthens 2–3 existing posts.

Coverage of agentic AI traffic — first-mover content

"Detecting Agentic AI Browsers" is the first piece in our category to address ChatGPT Atlas, OpenAI Operator, and Claude Computer Use as a distinct traffic class with a documented detection surface and a policy framework (block / allow-attribute / explicit-agent-path). Targets a query cluster ("detect chatgpt atlas", "block ai agent traffic", "operator bot detection") with essentially zero established competition as of May 2026.

Smarter VPN/proxy verdicts using dch as ground truth

The scanner now uses the datacenter-ASN flag (dch) to distinguish stale-cache verdicts from real VPN traffic. Matched IPs + vpn=true + residential ASN → CLEAN (cache residue from a previous VPN session). Route mismatch + datacenter ASN → DETECTED (real VPN exit even if our IP DB doesn't have it pinned by name). Eliminates the false-PROTON-VPN labels on residential IPs after VPN toggles, and catches real VPN exits our per-IP database hasn't ingested yet.

Live scanner: RESCAN button + cache-busting

Added a one-click RESCAN action in the scanner card header. Wipes localStorage, sessionStorage, cookies, and IndexedDB entries for the scanner's cache namespaces, then reloads with a unique ?_rescan=<ts> query so no cache layer (browser disk, BFCache, service worker, Cloudflare edge) can serve stale state. /api/verify calls now also send a fresh nonce per request and explicit cache: 'no-store'.

Route mismatch surfaced in network row

When our network edge sees a different visitor IP than what reaches our origin via Cloudflare (Brave + Proton TCP routing splits, CF WARP, etc.), the panel now shows both IPs stacked: A.B.C.D via CF + ↳ X.Y.Z.W via edge (VPN exit). The split itself is recorded, and the verdict reflects the underlying ASN signals rather than guessing.

Scanner can no longer hang on "Analysing now"

The legacy two-state machine had no exit when the network engine returned scanInconclusive=true twice. Bot poll now waits the full 4-second window and uses the LATEST device token (catches the engine's mid-window assessment refresh). Master 5-second safety timeout force-resolves if anything else stalls. Loading panel cross-fade switched from absolute positioning to CSS grid stacking — no more overflow behind the scanner foot when the details panel expands.

Device-intelligence reliability upgrade

Moved our device-intelligence integration to a Cloudflare-backed custom subdomain, improving load reliability in browsers with strict content blockers, with an automatic CDN fallback if DNS hasn't propagated. Applied across all pages that load the agent.

Dark editorial homepage restored, white-theme experiment reverted

A short-lived white redesign experiment clashed with the rest of the site (login, signup, dashboard, contact all run dark Space Grotesk + neon green). Restored the editorial dark theme so the homepage and post-signup flows share one visual system. Added a centered "Customer Voice" testimonial block with the residential-proxy quote, styled to match the existing crosshair / grid-overlay language.

Device-intelligence loader no longer hangs Device Intel on blocked browsers

When Brave Shields, Proton NetShield, or strict uBlock dropped the device-intelligence agent, the Device Intel rows were stuck on SCANNING… indefinitely. Hard 3-second timeout now resolves the row to a neutral state. Verify endpoint distinguishes "SDK genuinely blocked" (private/missing IP) from "stale public IP" so the panel paints an honest verdict either way.

Loading-state placeholders are loading-state-shaped

Detection signal rows used to ship as a literal ", " empty value, which read as broken-rendered output if a visitor opened the details panel during the bot-poll window. Replaced all 12 placeholders with "…" so the loading state reads as loading.

Smoother scanner cross-fade and row reveal

Loading→result transition uses cubic-bezier(0.22, 1, 0.36, 1) easing on opacity and Y-translate. Score-circle pops with a soft bounce. Result rows cascade in at 40/100/160/220 ms. Detail-grid items fade in staggered when the panel expands. Header colour swaps go through 0.4 s eased transitions instead of instant — feels like a polished SaaS product, not a 90s page reload.

Device-intelligence API key rotation

Routine credential rotation: server-side device-intel calls now use a freshly rotated secret managed entirely in environment configuration. Server CSP script-src, worker-src, and connect-src directives updated for the device-intelligence subdomain.

Customer voice section on the homepage

Added a centered testimonial block above the final CTA: residential-proxy detection drove the integration ROI in week three for a Series-A fintech. Styled in the editorial DM Mono / neon-green typography to match the rest of the site, with crosshair markers and a grid overlay matching the comparison and CTA bands.
April 2026 22 updates

Mobile polish — duplicate logo fix, overflow cleanup

Removed the duplicate Maskbreak logo that appeared on /login and /signup on phones (top-bar + split-panel brand rendered twice). Fixed horizontal overflow on the blog listing for small screens — comparison-table text scales down instead of clipping, CTA buttons stack full-width, tight containers no longer push content past the viewport on ≤420 px devices.

4 new blog posts targeting high-intent keywords

Added Stripe Fraud Detection API, Shopify Bot Detection, OAuth Signup Fraud, and How to Detect Residential Proxies in 2026. Each ships with Article + FAQ + BreadcrumbList schema, internal links to related posts, and its own canonical + OG cards.

BreadcrumbList schema across all 21 blog posts

Every blog post now emits BreadcrumbList JSON-LD alongside the existing Article and FAQPage schemas. Qualifies every post for breadcrumb rich snippets in Google SERPs and tightens site-wide structured-data coverage.

Dashboard + login load: instant first paint

Dashboard-init now fires from <head> before scripts parse (saves 50-200 ms cold) and stale-while-revalidate paints cached state instantly on returning visits. Redundant /api/user 2FA fetch removed. Device-intel call now uses requestIdleCallback. Login page preconnects accounts.google.com and prefetches /dashboard.

Dashboard chart redesign — SVG line + area with tooltip

Replaced stacked bars with a smooth SVG line + gradient-area chart for Clean vs. Threat traffic. Crosshair + floating tooltip on hover and tap. Skeleton shimmers while loading. Stronger empty states on the chart and the Recent Activity table. Staggered card fade-up, threat-row edge indicator, tighter row hover — all respecting prefers-reduced-motion.

Four dashboard bugs fixed

1. Chart range selector now re-renders with full 30-day window (server returned 14). 2. Playground validates the client token before firing so late SDK loads don't send empty requests. 3. Date-group headers in Recent Activity no longer orphaned after filtering. 4. Row hover moved from inline onmouseover to CSS :hover — no flicker on filter changes.

Typography + mobile polish sitewide

"API & Docs" renamed to "API Docs" across all 43 pages — the ampersand glyph under uppercase rendered visibly heavier than neighbouring nav items. Footer links dropped text-transform:uppercase so "IP Lookup" and "Integrations" read cleanly. Added a 400-px breakpoint for tiny phones; CTA buttons stack full-width; footer columns wrap to two-across.

X + LinkedIn footer links + SEO meta on legal pages

Visible X (Twitter) and LinkedIn SVG icons injected into the footer across 44 marketing pages. Added OG + Twitter card + Organization sameAs schema to integrations, privacy, terms, cookies, login, signup, and forgot-password. Removed noindex from legal pages — they were in the sitemap but blocked from indexing, inconsistent SEO signal now resolved.

Scanner IP check: trust the client token, fall back only on failure

Reverted an over-aggressive IP override that was masking legitimate VPN / proxy results. The scanner now trusts the decrypted client token as the source of truth for IP, country, and VPN/proxy flags — which reflects the client's actual connection at scan time. CF-Connecting-IP is used only when the token couldn't resolve (antidetect browser blocking the SDK). Result: toggling VPN on/off now shows correctly every time.

12-point security hardening — secrets, auth, 2FA

Secrets management moved fully to environment configuration. Face login now requires a server-verified liveness check. Admin endpoint uses a separate key with constant-time comparison. 2FA setup requires password re-auth. Stricter validation on upstream lookups. Scan IDs use crypto.randomBytes.

Core Web Vitals overhaul — 6 optimizations

The liveness-check SDK (1.97 MB) lazy-loaded on demand instead of blocking page render. Device intelligence deferred to first user interaction. Blog hero images preloaded with explicit dimensions. Shared CSS extracted to external cacheable files — 136 KB of duplicated inline CSS removed across 31 pages. Google Tag Manager moved out of critical rendering path.

WCAG compliance — focus indicators, skip-link, form labels

Global :focus-visible accent outlines on all interactive elements. Skip-to-content link on every page. Contact form labels properly associated with inputs. Heading hierarchy violations fixed.

Custom 404 page + branded error handling

Unknown routes now return a branded 404 page with popular destination links instead of a raw text error. API routes return structured JSON errors.

Blog: How Residential Proxies Bypass Cloudflare Bot Fight Mode

New analysis piece covering the three specific bypasses (clean ASN, real TLS fingerprints, valid JS execution) and why detection must move from the network layer to the device layer.

SEO audit — 16 title truncations fixed, all JSON-LD validated

Shortened 16 page titles and 13 meta descriptions to avoid Google SERP truncation. Validated all 50 structured data blocks site-wide — zero errors. Case study Article schemas fixed with missing required fields.

Accessibility improvements across all pages

Added <main> landmarks to all pages, removed user-scalable viewport restrictions, and improved ARIA labels across 34 pages for better screen reader and keyboard navigation support.

Mobile PageSpeed 79 → 93 via async font loading

Switched Google Fonts to non-blocking async preload across all pages. Mobile PageSpeed score improved from 79 to 93, reducing render-blocking resources and improving LCP on low-bandwidth connections.

CSP headers hardened, Mozilla Observatory score → A

Fixed Content Security Policy headers to properly allowlist Google Ads and GTM. Added Permissions-Policy header to disable the deprecated FLEDGE API. Mozilla Observatory security score improved to A.

3 new high-volume blog posts published

Published "IP Reputation API Guide", "Device Fingerprinting API", and "Proxy Detection" — targeting high-volume search keywords with 1K–10K monthly searches. All pages include structured data and optimized meta.

OTP email redesign with individual digit boxes

Redesigned OTP verification emails with a cleaner layout featuring individual digit boxes for each character. Improved visual hierarchy and copy to reduce confusion during the signup flow.

Google OAuth now uses proper RS256 JWKS signature verification

Google OAuth tokens are now cryptographically verified with RS256 signatures against Google's JWKS public key endpoint on every auth request, pinning issuer, audience, and expiry.

HSTS preload, CORP headers, and CSP violation reporting

Added HSTS preload directive, Cross-Origin-Resource-Policy header, and a CSP violation reporting endpoint to capture and monitor any policy breaches in production.
March 2026 5 updates

Organization schema added to homepage

Added JSON-LD Organization schema markup to the homepage, including name, URL, logo, contact point, and social profiles. Improves Google Knowledge Graph presence and enables rich results in search.

Footer expanded to 4-column layout

Redesigned the site-wide footer with a 4-column layout including dedicated sections for comparison pages (/vs/), industry landing pages (/for/), legal, and platform links. Improves internal linking for SEO.

5 competitor comparison pages launched

Launched dedicated comparison pages for vs IPQS, vs SEON, vs Sift, vs Kount, and vs minFraud. Each page includes an objective feature matrix, pricing comparison, and Maskbreak's advantages.

4 industry landing pages launched

Launched tailored landing pages for SaaS, Fintech, E-Commerce, and Gaming verticals. Each page addresses the specific fraud vectors and use cases relevant to that industry with targeted CTAs.

10 SEO blog posts covering modern fraud vectors

Published 10 in-depth blog posts covering antidetect browsers, credential stuffing, proxy evasion, threat intelligence, and residential proxy abuse. Total indexed blog content now at 15 posts.
February 2026 4 updates

Migrated to Turso cloud database

Replaced local SQLite with Turso cloud database for persistent, multi-region storage. Eliminates data loss on container restarts and enables low-latency reads across global edge locations.

Rate limiting with per-IP and per-endpoint controls

Added configurable rate limiting across all API endpoints. Controls are applied per IP and per endpoint independently, with exponential backoff headers returned on limit breach.

New /api/device-intel endpoint launched

Launched /api/device-intel combining device signals with network intelligence. Returns a unified risk score with device-level and network-level signals in a single call.

Open Beta — 10,000 requests/month, free, no card required

Maskbreak entered public Open Beta. All features available for free with a limit of 10,000 API requests per month. No credit card required to sign up. Rate limits apply to prevent abuse. (The free tier has since been raised to 1,000 requests per hour.)
January 2026 3 updates

Closed alpha with first 50 testers

Ran a closed alpha with 50 hand-picked testers from SaaS, fintech, and e-commerce backgrounds. Feedback directly shaped the v1 API schema, response format, and signal set.

Infrastructure setup on Railway with Cloudflare CDN and DNSSEC

Initial production infrastructure deployed on Railway with Cloudflare as CDN and DNS provider. DNSSEC enabled on the maskbreak.com domain. Global edge caching configured for static assets.

Maskbreak founded

Started building the fraud detection API we wished existed — one that catches residential proxies, antidetect browsers, and bot farms that every legacy vendor misses. Day zero.