Last active
June 23, 2024 18:01
-
-
Save mikeckennedy/97ea085358e7ee663e1afa430fe0d979 to your computer and use it in GitHub Desktop.
Turnstile Python Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Short usage example in form post handler on the server: | |
def form_post_handler(): | |
turnstile_response = form_dict.get('cf-turnstile-response') | |
validation_response = turnstile.validate(turnstile_response, get_client_ip()) | |
if not validation_response.success: | |
# Handle the error | |
... | |
# All is good from here out... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<form ...> | |
<div class="cf-turnstile" data-sitekey="YOUR_KEY" | |
data-action="some-tag-to-track" | |
data-theme="dark" | |
data-callback="javascriptCallback"></div> | |
</form> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from typing import Optional | |
import pydantic | |
import requests | |
cloudflare_secret_key: Optional[str] = None | |
class SiteVerifyRequest(pydantic.BaseModel): | |
secret: str | |
response: str | |
remoteip: Optional[str] | |
class SiteVerifyResponse(pydantic.BaseModel): | |
success: bool | |
challenge_ts: Optional[str] | |
hostname: Optional[str] | |
error_codes: list[str] = pydantic.Field(alias="error-codes", default_factory=list) | |
action: Optional[str] | |
cdata: Optional[str] | |
def validate(turnstile_response: str, user_ip: Optional[str]) -> SiteVerifyResponse: | |
if not cloudflare_secret_key: | |
raise Exception("You must set your cloudflare_secret_key before using this function.") | |
if not turnstile_response: | |
model = SiteVerifyResponse(success=False, hostname=None) | |
model.error_codes.append('Submitted with no cloudflare client response') | |
return model | |
url = 'https://challenges.cloudflare.com/turnstile/v0/siteverify' | |
model = SiteVerifyRequest(secret=cloudflare_secret_key, response=turnstile_response, remoteip=user_ip) | |
try: | |
resp = requests.post(url, data=model.dict()) | |
if resp.status_code != 200: | |
model = SiteVerifyResponse(success=False, hostname=None) | |
model.error_codes.extend([ | |
f'Failure status code: {resp.status_code}', | |
f'Failure details: {resp.text}']) | |
return model | |
site_response = SiteVerifyResponse(**resp.json()) | |
return site_response | |
except Exception as x: | |
model = SiteVerifyResponse(success=False, hostname=None) | |
model.error_codes.extend([ | |
f'Failure status code: Unknown', | |
f'Failure details: {x}']) | |
return model |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment