Skip to content

Instantly share code, notes, and snippets.

@mikeckennedy
Last active June 23, 2024 18:01
Show Gist options
  • Save mikeckennedy/97ea085358e7ee663e1afa430fe0d979 to your computer and use it in GitHub Desktop.
Save mikeckennedy/97ea085358e7ee663e1afa430fe0d979 to your computer and use it in GitHub Desktop.
Turnstile Python Example
# 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...
<form ...>
<div class="cf-turnstile" data-sitekey="YOUR_KEY"
data-action="some-tag-to-track"
data-theme="dark"
data-callback="javascriptCallback"></div>
</form>
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