https://github.com/llybin/drf-recaptcha
Django REST framework reCAPTCHA
https://github.com/llybin/drf-recaptcha
django django-rest-framework python recaptcha recaptcha-v2 recaptcha-v3
Last synced: 3 months ago
JSON representation
Django REST framework reCAPTCHA
- Host: GitHub
- URL: https://github.com/llybin/drf-recaptcha
- Owner: llybin
- License: mit
- Created: 2019-12-03T17:57:00.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2025-09-15T11:15:58.000Z (10 months ago)
- Last Synced: 2025-10-05T20:14:54.344Z (9 months ago)
- Topics: django, django-rest-framework, python, recaptcha, recaptcha-v2, recaptcha-v3
- Language: Python
- Homepage: https://pypi.org/project/drf-recaptcha/
- Size: 108 KB
- Stars: 95
- Watchers: 1
- Forks: 16
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Funding: .github/FUNDING.yml
- License: LICENSE.md
Awesome Lists containing this project
README
# Django REST reCAPTCHA
**Django REST reCAPTCHA v2 and v3 field serializer**
[](https://github.com/sponsors/llybin)
[](https://github.com/llybin/drf-recaptcha/actions)
[](https://www.codacy.com/app/llybin/drf-recaptcha?utm_source=github.com&utm_medium=referral&utm_content=llybin/drf-recaptcha&utm_campaign=Badge_Grade)
[](https://www.codacy.com/app/llybin/drf-recaptcha?utm_source=github.com&utm_medium=referral&utm_content=llybin/drf-recaptcha&utm_campaign=Badge_Coverage)
[](https://github.com/astral-sh/ruff)
[](https://pypi.org/project/drf-recaptcha/)
[](https://pypi.org/project/drf-recaptcha/)
[](https://pypi.org/project/drf-recaptcha/)
## Requirements
* Python: 3.10, 3.11, 3.12, 3.13
* Django: 4.2, 5.0, 5.1, 5.2
* DRF: 3.14, 3.15, 3.16
## Installation
1. [Sign up for reCAPTCHA](https://www.google.com/recaptcha/)
2. Install with `pip install drf-recaptcha`
3. Add `"drf_recaptcha"` to your `INSTALLED_APPS` settings.
4. Set in settings `DRF_RECAPTCHA_SECRET_KEY`
```python
INSTALLED_APPS = [
...,
"drf_recaptcha",
...,
]
...
DRF_RECAPTCHA_SECRET_KEY = "YOUR SECRET KEY"
```
## Usage
```python
from rest_framework.serializers import Serializer, ModelSerializer
from drf_recaptcha.fields import ReCaptchaV2Field, ReCaptchaV3Field
from feedback.models import Feedback
class V2Serializer(Serializer):
recaptcha = ReCaptchaV2Field()
...
class GetOTPView(APIView):
def post(self, request):
serializer = V2Serializer(data=request.data, context={"request": request})
serializer.is_valid(raise_exception=True)
...
class V3Serializer(Serializer):
recaptcha = ReCaptchaV3Field(action="example")
...
class V3WithScoreSerializer(Serializer):
recaptcha = ReCaptchaV3Field(
action="example",
required_score=0.6,
)
...
class GetReCaptchaScore(APIView):
def post(self, request):
serializer = V3WithScoreSerializer(data=request.data, context={"request": request})
serializer.is_valid()
score = serializer.fields['recaptcha'].score
...
class FeedbackSerializer(ModelSerializer):
recaptcha = ReCaptchaV2Field()
class Meta:
model = Feedback
fields = ("phone", "full_name", "email", "comment", "recaptcha")
def validate(self, attrs):
attrs.pop("recaptcha")
...
return attrs
class DynamicContextSecretKey(APIView):
def post(self, request):
if request.platform == "android":
recaptcha_secret_key = "SPECIAL_FOR_ANDROID"
else:
recaptcha_secret_key = "SPECIAL_FOR_IOS"
serializer = WithReCaptchaSerializer(
data=request.data,
context={
"request": request,
"recaptcha_secret_key": recaptcha_secret_key,
},
)
serializer.is_valid(raise_exception=True)
...
class DynamicContextSecretKey(GenericAPIView):
serializer_class = WithReCaptchaSerializer
def get_serializer_context(self):
if self.request.platform == "android":
recaptcha_secret_key = "SPECIAL_FOR_ANDROID"
else:
recaptcha_secret_key = "SPECIAL_FOR_IOS"
context = super().get_serializer_context()
context.update({"recaptcha_secret_key": recaptcha_secret_key})
return context
class MobileSerializer(Serializer):
recaptcha = ReCaptchaV3Field(secret_key="SPECIAL_MOBILE_KEY", action="feedback")
...
```
## Settings
`DRF_RECAPTCHA_SECRET_KEY` - set your Google reCAPTCHA secret key. Type: str.
`DRF_RECAPTCHA_DEFAULT_V3_SCORE` - by default: `0.5`. Type: float.
`DRF_RECAPTCHA_ACTION_V3_SCORES` - by default: `{}`. Type: dict. You can define specific score for each action e.g.
`{"login": 0.6, "feedback": 0.3}`
`DRF_RECAPTCHA_DOMAIN` - by default: `www.google.com`. Type: str.
`DRF_RECAPTCHA_PROXY` - by default: `{}`. Type: dict. e.g.
`{'http': 'http://127.0.0.1:8000', 'https': 'https://127.0.0.1:8000'}`
`DRF_RECAPTCHA_VERIFY_REQUEST_TIMEOUT` - by default: `10`. Type: int.
### Priority of secret_key value
1. settings `DRF_RECAPTCHA_SECRET_KEY`
2. the argument `secret_key` of field
3. request.context["recaptcha_secret_key"]
### Silence the check error
If you need to disable the error, you can do so using the django settings.
```python
SILENCED_SYSTEM_CHECKS = ['drf_recaptcha.checks.recaptcha_system_check']
```
## reCAPTCHA v3
Validation is passed if the score value returned by Google is greater than or equal to required score.
Required score value: `0.0 - 1.0`
### Priority of score value
If not defined or zero in current item then value from next item.
1. Value for action in settings `DRF_RECAPTCHA_ACTION_V3_SCORES`
2. Value in argument `required_score` of field
3. Default value in settings `DRF_RECAPTCHA_DEFAULT_V3_SCORE`
4. Default value `0.5`
## Testing
Set `DRF_RECAPTCHA_TESTING=True` in settings, no request to Google, no warnings, `DRF_RECAPTCHA_SECRET_KEY` is not
required, set returning verification result in setting below.
`DRF_RECAPTCHA_TESTING_PASS=True|False` - all responses are pass, default `True`.
Use `from django.test import override_settings`
## Credits
[django-recaptcha](https://github.com/praekelt/django-recaptcha)
reCAPTCHA copyright 2012 Google.