Jump to content

hCaptcha

From Wikitech


Please use caution when referencing concepts or code contained in the private https://docs.hcaptcha.com/enterprise documentation, as well as to private code used in the WMF proxy to hCaptcha

hCaptcha is a proprietary device fingerprinting and CAPTCHA platform as a service with applications for bot detection. Wikimedia Foundation is using this service for all account creations, edits made using most editing interfaces, and for repeated failed login attempts on some wikis. Users with the skipcaptcha right (autoconfirmed users) are exempted and do not see hCaptcha.

Wikimedia uses hCaptcha Enterprise's First-Party feature, which routes all client traffic through a Wikimedia controlled proxy.

Design

The basic idea is the same as the standard hCaptcha flow. However, to minimize impact on user privacy, user requests do not go directly to hCaptcha servers, but are sent through our proxy, which strips IP addressess, cookies and other identifying information.

Client Side

We use hCaptcha for most editing interfaces and for all account creations. This involves loading code and assets using the hCaptcha reverse proxy, and displaying the hCaptcha widget, and then executing hCaptcha when a user submits the form.

Loading hCaptcha

We load hCaptcha at different times depending on the interface that is used:

  • For the desktop wikitext editor, the VisualEditor interface, Special:UserLogin, and Special:CreateAccount the hCaptcha JS is loaded when a user interacts with the form
  • For the mobile wikitext source editor, the hCaptcha JS is loaded when the user opens the save changes step

Loading hCaptcha first loads the secure-api.js file and executes it. This JS file is self-hosted and is stored in the static directory. This causes several other requests to be made through the reverse proxy to fetch additional data and files.

Rendering and executing hCaptcha

When the hCaptcha JS is loaded, the hCaptcha widget can be rendered. On WMF wikis this is displayed in "invisible" mode, which means no visible checkbox for the user. The widget is rendered at different times depending on the form being used

When a user submits the form we halt the submission and execute hCaptcha. This usually makes several additional requests through the reverse proxy and may show a visual challenge to the user to complete. If successful, a token is passed back from hCaptcha that we append to the form submission that is validated by the server

Server side

Mediawiki

Server side CAPTCHA validation flow

MediaWiki handles hCaptcha in most situations like any other CAPTCHA. This means that classes like EditPage leave the hCaptcha specific checks to the hCaptcha code and get a pass/fail for the CAPTCHA. However, unlike question based CAPTCHAs a failure for the CAPTCHA is more likely due to request spoofing or an API request that did not show a user a hCaptcha challenge.

hCaptcha passes the token passed by the client in the request to the siteverify API which will return a success if the token is valid. If the token is valid then the user has passed the CAPTCHA. If this request fails or responds that the token is not valid, then the user does not pass the CAPTCHA.

In some situations MediaWiki may require a stricter check, which leads the server to respond with a CAPTCHA failure but with the stricter sitekey to be used. This currently is used to enforce that a user sees a visual challenge when configured by the community through an AbuseFilter.

FancyCaptcha fallback mechanism

MediaWiki keeps an eye on the hCaptcha and will failover to use FancyCaptcha (the CAPTCHA in place before hCaptcha is enabled on a wiki). This happens if more than 5 requests in the last minute to the siteverify API have either failed with a HTTP error or returned invalid JSON

hcaptcha-proxy

Hcaptcha wmf design
  • Forwards requests to hCaptcha
  • Strips any identifying information by unsetting various headers
  • Hashes client IP address, <%= @nginx_ipblinding_conf %> blocks in NginX-'s (see below)
FIXME: Out of date. Should be updated by Traffic to include anycast setup info.

CDNLoad Balancerreverse proxyhcaptcha upstream ("the internet")

  • proxoid.discovery.wmnet (active/active service)
  • The reverse proxy is a basic nginx installation Currently (Sept 2025) the proxy is installed on the url_downloader hosts.

Configuration

On https://dashboard.hcaptcha.com, we have several sitekeys defined for production wikis. Each sitekey is used by different actions and interfaces as configured in operations/mediawiki-config.

The sitekeys all share a secret key, which is defined in:

mediawiki-config

There are toggles in wmf-config/InitialiseSettings.php that define wiki has hCaptcha functionality enabled or disabled. Changing these toggles will enable/disable hCaptcha as required, where a wiki without hCaptcha will use FancyCaptcha instead:

  • wmgEnableHCaptcha controls whether hCaptcha is enabled at all on a wiki
  • wmgEnableHCaptchaEditing controls whether hCaptcha is enabled for editing via the desktop wikitext editor
  • wgHCaptchaEnabledInMobileFrontend controls whether hCaptcha is enabled for edits made via the mobile source editor
  • wmgEnableHCaptchaAccountCreationAPI controls whether hCaptcha is enabled for the account creation API
  • wmgEnableHCaptchaForBadLogin controls whether hCaptcha is enabled for repeated failed login attempts
  • wmgEnableHCaptchaUploadWizard controls whether hCaptcha is enabled for the file upload wizard

Here is an example patch to do this: I80886c

Puppet

Cookies

The proxy removes all cookies except hmt_id, per Idb012f and I87190f.

Monitoring

Runbook

Depooling an hcaptcha-proxy instance / an instance is down

FIXME: Explain automatic fallback due to the anycast setup, should be updated by Traffic.

Completely disable hCaptcha

In case of emergency, disable this functionality by toggling wmgEnableHCaptcha in wmf-config/InitialiseSettings.php to false for the wikis to disable hCaptcha on (or default if everywhere).

Here is an example patch to do this: I80886c

Enable emergency CAPTCHA

If all edits should encounter a visual challenge (otherwise known as emergency CAPTCHA), then log into the hCaptcha dashboard and change the relevant sitekeys to "always challenge" mode.

Note that in cases of bot attack, hCaptcha will likely adapt the rate of visual challenges in the normal 99.9% mode (so this should not be done unless necessary)

Proxy smoke test

FIXME: Smoke test requests should be documented by ServiceOps or Traffic.

Contact information

The hCaptcha integration with on-wiki workflows is managed by the Product Safety and Integrity team as part of the WE4.2 and WE4.10 anti-abuse signals hCaptcha project.

The proxy infrastructure is managed by Traffic SRE.