django-recaptcha adds a captcha field to Django forms, with a one-widget-per-page catch
Django reCAPTCHA form field/widget integration app.
At a glance
- What is it?
- django-recaptcha is a small Django app that renders Google's reCAPTCHA checkbox, invisible and V3 widgets inside a form field and verifies the token server side. The integration is a few lines of settings, and the sharp edge is that the widgets support only a single form with a single widget per page by default.
- Who is it for?
- django-recaptcha suits a Django project that wants reCAPTCHA on a form with minimal glue, and it suits teams that need the invisible or V3 variants plus per field key overrides without writing their own widget. It is the wrong choice if your page has several forms with captchas, because the widgets support only a single form with a single widget on each page by default, and a poor match if you need error messages in a language outside the eight that ship with translations.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 21, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One form field, three captcha variants, server side verification
django-recaptcha is described as a Django reCAPTCHA form field and widget integration app. That description is exactly what it is, and the smallness is the feature: the problem is that a Django form has no built in way to prove a human filled it in, and every project solves that by writing the same three pieces of glue. A widget that renders Google's script and the site key, a field that carries the token, and a call to Google's verification endpoint during form validation.
This package supplies all three. The quickest route is the included ReCaptchaField field class, used in a form like any other Django field:
from django import forms
from django_recaptcha.fields import ReCaptchaField
class FormWithCaptcha(forms.Form):
captcha = ReCaptchaField()Verification is part of field validation, so an invalid or missing token makes the form invalid rather than raising an error in your view code. The field is deliberately a Django field rather than a decorator or a middleware, which means it composes with the rest of the form machinery, including the forms documentation's own guidance on rendering options and rendering fields manually.
Under the hood the package uses a modified version of the Python reCAPTCHA client, which is included in the package as client.py. Bundling a modified copy of the client is worth noting: it means the verification code does not come and go with an upstream release, so the maintenance of that copy falls to this project rather than to the client library's maintainers.
The audience is Django developers who need captcha on a form and would rather not build the widget, the token handling and the verification call themselves.
Three widgets, and the one-widget-per-page default
The ReCaptchaField class can be rendered with three different widgets. ReCaptchaV2Checkbox is the Google reCAPTCHA V2 Checkbox, ReCaptchaV2Invisible is V2 Invisible, and ReCaptchaV3 is V3. The checkbox is the default, so a field with no arguments renders the variant most people mean when they say captcha.
Switching is a matter of replacing the widget:
from django import forms
from django_recaptcha.fields import ReCaptchaField
from django_recaptcha.widgets import ReCaptchaV2Invisible
class FormWithCaptcha(forms.Form):
captcha = ReCaptchaField(widget=ReCaptchaV2Invisible)Two further customisation points exist, and they are separate from each other. The widget supports data attributes such as data-theme and data-size, which are forwarded through an attrs dictionary:
captcha = fields.ReCaptchaField(
widget=widgets.ReCaptchaV2Checkbox(
attrs={
'data-theme': 'dark',
'data-size': 'compact',
}
)
)
# The ReCaptchaV2Invisible widget
# ignores the "data-size" attribute in favor of 'data-size="invisible"'And the reCAPTCHA API parameters sent alongside the widget are set through an api_params dictionary, which is urlencoded and appended to the API URL:
captcha = fields.ReCaptchaField(
widget=widgets.ReCaptchaV2Checkbox(
api_params={'hl': 'cl', 'onload': 'onLoadFunc'}
)
)The limitation to plan around is stated plainly in the documentation: by default, the widgets provided only support a single form with a single widget on each page. A page with two captcha protected forms, or a form rendered twice, needs work beyond the default. It is the first thing to check if you were planning a multi form layout.
Installing the app and setting the two keys
The installation sequence starts outside the code, with signing up for reCAPTCHA to get the Google keys. The package is then installed from PyPI:
pip install django-recaptchaThe app is registered like any other Django application:
INSTALLED_APPS = [
...,
'django_recaptcha',
...
]And the keys generated at signup go into the production settings:
RECAPTCHA_PUBLIC_KEY = 'MyRecaptchaKey123'
RECAPTCHA_PRIVATE_KEY = 'MyRecaptchaPrivateKey456'Two details here matter more than they look. The public key is embedded in the page and the private key is the one that signs the verification request, so the private key must never reach a template; the package handles that by reading it from settings. And omitting these settings does not fail loudly: it defaults to a set of test keys, which is convenient for local work and dangerous in production if a deployment forgets the setting. If you want keys that differ per environment, they can be specified per field by passing the public_key or private_key parameters to ReCaptchaField, and those parameters are used instead of your project settings.
Two optional settings round out the configuration. If you need a proxy, RECAPTCHA_PROXY takes a dictionary of proxies:
RECAPTCHA_PROXY = {'http': 'http://127.0.0.1:8000', 'https': 'https://127.0.0.1:8000'}And in the event that www.google.com is not accessible, the RECAPTCHA_DOMAIN setting can be changed to www.recaptcha.net, which changes the Google JavaScript API domain as well as the client side field verification domain, so both halves of the round trip move together.
Translation coverage is the part most likely to surprise you
The language of the captcha is set with the hl parameter, and the documentation links to the language codes for the options. The catch is stated right after it: translations need to be added to this package for the errors to be shown correctly.
The package currently has error translations for eight language codes: es, fr, nl, pl, pt_BR, ru, zh_CN and zh_TW. That is the list of languages in which a validation failure message will be readable rather than falling back to English. If your users read German, Italian, Japanese, Korean or Arabic, you are outside the shipped translations, and the fix is a contribution to the package rather than a configuration change.
That is the practical shape of this dependency: the integration code is small and unlikely to need changing, but the user facing strings are a translation surface that has to be maintained by the community.
The V3 variant has its own documented areas, since the table of contents carries separate sections for the reCAPTCHA V3 Score and the reCAPTCHA V3 Action. Those two are the parts of V3 that differ from a checkbox: instead of a pass or fail there is a score you can threshold, and an action name that ties the token to the specific action on your site. A V3 integration is therefore a policy decision in your view code, deciding what score counts as a pass, and the field and widget here are only the transport for it.
BSD-3-Clause, a namespace rename and an unreleased version
The licence is BSD-3-Clause, recorded in the packaging metadata, with a LICENSE file at the repository root. BSD-3-Clause is permissive: it asks for the copyright notice, the warranty disclaimer and no endorsement claims, with no copyleft requirement on code that uses the package. For a Django app that many projects will depend on, that is a low friction licence choice.
The version history explains one thing you may hit when upgrading. Release 3.0.0 added Django 4.0 support, 4.0.0 was a package namespace rename, and 4.1.0 was an incremental improvement released on 2025-03-28. The namespace rename is the one to note, because a change in how the package is named on PyPI means existing dependency pins and import paths have to be revisited rather than bumped.
The current state of the repository is ahead of the last release. The packaging metadata carries version 4.2.0 while the most recent published release is 4.1.0, so main is the next release in preparation. The last push was on 2026-10-12, and the repository is not archived, so the work is current even though the version number has not moved in public for a while.
The supported matrix is declared rather than implied. The project is tested with Python 3.10 through 3.15 and with Django 5.2, 6.0 and 6.1, and the classifiers list each of those Django versions and each Python version, with the development status marked as Production/Stable. That is a reasonable matrix for an app that depends on Django's form and template machinery, and it tells you which combinations of Python and Django you can expect to work.
The repository also carries a tox.ini for running the test matrix, a.coveragerc with the coverage configuration, a pre-commit configuration, a CHANGELOG.md, a SECURITY.md, an AUTHORS.md, a code of conduct and an ADOPTERS.md, and the authors are listed as individual contributors together with Torchbox, the company behind the package.
Editorial conclusion
django-recaptcha suits a Django project that wants reCAPTCHA on a form with minimal glue, and it suits teams that need the invisible or V3 variants plus per field key overrides without writing their own widget. It is the wrong choice if your page has several forms with captchas, because the widgets support only a single form with a single widget on each page by default, and a poor match if you need error messages in a language outside the eight that ship with translations. Before adopting, sign up for reCAPTCHA keys and set RECAPTCHA_PUBLIC_KEY and RECAPTCHA_PRIVATE_KEY in production settings, confirm your users can reach the Google script domain or switch RECAPTCHA_DOMAIN to www.recaptcha.net, and check that the page layout carries only one captcha widget.
Frequently asked questions
How do I install django-recaptcha in a Django project?
Sign up for reCAPTCHA to get your keys, run pip install django-recaptcha, add 'django_recaptcha' to INSTALLED_APPS, and set RECAPTCHA_PUBLIC_KEY and RECAPTCHA_PRIVATE_KEY in your production settings. If those settings are omitted the package falls back to a set of test keys.
Which reCAPTCHA variants does django-recaptcha support?
Google reCAPTCHA V2 Checkbox, which is the default widget, Google reCAPTCHA V2 Invisible, and Google reCAPTCHA V3. You choose by replacing the widget on the ReCaptchaField class.
Can I use django-recaptcha when www.google.com is blocked?
Yes. Set RECAPTCHA_DOMAIN to 'www.recaptcha.net', which changes the Google JavaScript API domain as well as the client side field verification domain, so the browser and the server side check both use the alternative domain.
What licence is django-recaptcha released under?
It is licensed under the BSD-3-Clause licence, recorded in the packaging metadata with the LICENSE file in the repository root. The package is published on PyPI as django-recaptcha.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/django-recaptcha-django-recaptcha)Was this useful?