cloudstile


Namecloudstile JSON
Version 2.0.1 PyPI version JSON
download
home_pagehttps://github.com/notaussie/cloudstile
SummaryUnofficial Cloudflare Turnstile library for Python with async and sync support.
upload_time2025-07-26 07:44:21
maintainerNone
docs_urlNone
authorNotAussie
requires_python<4.0,>=3.9
licenseMIT
keywords cloudflare turnstile captcha
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # `⛅` Cloudstile
An unofficial Cloudflare Turnstile library with both asynchronous and synchronous support out of the box.

[![codecov](https://codecov.io/github/NotAussie/cloudstile/branch/main/graph/badge.svg?token=6VKWB9GXEU)](https://codecov.io/github/NotAussie/cloudstile) [![Tests](https://github.com/NotAussie/cloudstile/actions/workflows/tests.yml/badge.svg)](https://github.com/NotAussie/cloudstile/actions/workflows/tests.yml) [![Pylint](https://github.com/NotAussie/cloudstile/actions/workflows/pylint.yml/badge.svg)](https://github.com/NotAussie/cloudstile/actions/workflows/pylint.yml) [![Mypy](https://github.com/NotAussie/cloudstile/actions/workflows/mypy.yml/badge.svg)](https://github.com/NotAussie/cloudstile/actions/workflows/mypy.yml)

## `📥` Installation
**Cloudstile** is available for download via PyPI. To install it, simply do:
```shell
pip install cloudstile
```

## `🎭` Example

Here are some basic examples of how to validate a user's turnstile token.

> [!WARNING]
> These examples expect the user's IP to be transparent. If you're using something like Cloudflare's proxy service, then you'll need to access the corresponding header for your use case.

### `🍷` Quart *(Asynchronous)*

```python
from quart import Quart, request, jsonify
from cloudstile import AsyncTurnstile

app = Quart(__name__)
turnstile = AsyncTurnstile(token="...")

@app.route("/submit", methods=["POST"])
async def submit():

    body = await request.form

    response = await turnstile.validate(
        body.get("cf-turnstile-response", "..."),
        request.remote_addr,
    )

    return jsonify(response.model_dump()) # <- Response is a pydantic object

```

### `🏃‍♀️` FastAPI *(Asynchronous)*

```python
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from cloudstile import AsyncTurnstile

app = FastAPI()
turnstile = AsyncTurnstile(token="...")

@app.post("/submit")
async def submit(request: Request):

    body = await request.form()

    response = await turnstile.validate(
        body.get("cf-turnstile-response", "..."),
        request.client.host,
    )

    return JSONResponse(response.model_dump()) # <- Response is a pydantic object

```


### `🦥` Flask *(Synchronous)*

```python
from flask import Flask, request, jsonify
from cloudstile import SyncTurnstile

app = Flask(__name__)
turnstile = SyncTurnstile(token="...")

@app.route("/submit", methods=["POST"])
def submit():

    body = request.form

    response = turnstile.validate(
        body.get("cf-turnstile-response", "..."),
        request.remote_addr,
    )

    return jsonify(response.model_dump()) # <- Response is a pydantic object

```

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/notaussie/cloudstile",
    "name": "cloudstile",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4.0,>=3.9",
    "maintainer_email": null,
    "keywords": "cloudflare, turnstile, captcha",
    "author": "NotAussie",
    "author_email": "notaussie@duck.com",
    "download_url": "https://files.pythonhosted.org/packages/82/1b/c7c93a5923b827e4ce9b2df0066afeae56513b8e3391587c7b7398fd3659/cloudstile-2.0.1.tar.gz",
    "platform": null,
    "description": "# `\u26c5` Cloudstile\nAn unofficial Cloudflare Turnstile library with both asynchronous and synchronous support out of the box.\n\n[![codecov](https://codecov.io/github/NotAussie/cloudstile/branch/main/graph/badge.svg?token=6VKWB9GXEU)](https://codecov.io/github/NotAussie/cloudstile) [![Tests](https://github.com/NotAussie/cloudstile/actions/workflows/tests.yml/badge.svg)](https://github.com/NotAussie/cloudstile/actions/workflows/tests.yml) [![Pylint](https://github.com/NotAussie/cloudstile/actions/workflows/pylint.yml/badge.svg)](https://github.com/NotAussie/cloudstile/actions/workflows/pylint.yml) [![Mypy](https://github.com/NotAussie/cloudstile/actions/workflows/mypy.yml/badge.svg)](https://github.com/NotAussie/cloudstile/actions/workflows/mypy.yml)\n\n## `\ud83d\udce5` Installation\n**Cloudstile** is available for download via PyPI. To install it, simply do:\n```shell\npip install cloudstile\n```\n\n## `\ud83c\udfad` Example\n\nHere are some basic examples of how to validate a user's turnstile token.\n\n> [!WARNING]\n> These examples expect the user's IP to be transparent. If you're using something like Cloudflare's proxy service, then you'll need to access the corresponding header for your use case.\n\n### `\ud83c\udf77` Quart *(Asynchronous)*\n\n```python\nfrom quart import Quart, request, jsonify\nfrom cloudstile import AsyncTurnstile\n\napp = Quart(__name__)\nturnstile = AsyncTurnstile(token=\"...\")\n\n@app.route(\"/submit\", methods=[\"POST\"])\nasync def submit():\n\n    body = await request.form\n\n    response = await turnstile.validate(\n        body.get(\"cf-turnstile-response\", \"...\"),\n        request.remote_addr,\n    )\n\n    return jsonify(response.model_dump()) # <- Response is a pydantic object\n\n```\n\n### `\ud83c\udfc3\u200d\u2640\ufe0f` FastAPI *(Asynchronous)*\n\n```python\nfrom fastapi import FastAPI, Request\nfrom fastapi.responses import JSONResponse\nfrom cloudstile import AsyncTurnstile\n\napp = FastAPI()\nturnstile = AsyncTurnstile(token=\"...\")\n\n@app.post(\"/submit\")\nasync def submit(request: Request):\n\n    body = await request.form()\n\n    response = await turnstile.validate(\n        body.get(\"cf-turnstile-response\", \"...\"),\n        request.client.host,\n    )\n\n    return JSONResponse(response.model_dump()) # <- Response is a pydantic object\n\n```\n\n\n### `\ud83e\udda5` Flask *(Synchronous)*\n\n```python\nfrom flask import Flask, request, jsonify\nfrom cloudstile import SyncTurnstile\n\napp = Flask(__name__)\nturnstile = SyncTurnstile(token=\"...\")\n\n@app.route(\"/submit\", methods=[\"POST\"])\ndef submit():\n\n    body = request.form\n\n    response = turnstile.validate(\n        body.get(\"cf-turnstile-response\", \"...\"),\n        request.remote_addr,\n    )\n\n    return jsonify(response.model_dump()) # <- Response is a pydantic object\n\n```\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Unofficial Cloudflare Turnstile library for Python with async and sync support.",
    "version": "2.0.1",
    "project_urls": {
        "Homepage": "https://github.com/notaussie/cloudstile",
        "Repository": "https://github.com/notaussie/cloudstile"
    },
    "split_keywords": [
        "cloudflare",
        " turnstile",
        " captcha"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "1f57a38c2b3604088bff2b824c049e7948b199e2e97b6d3ed461cd8baaf8cad9",
                "md5": "c29cd096ce3f0fa576384c794b6d32d7",
                "sha256": "919a270da2f92a5128347f294c185b0e9a8b93e85f0d1b5b1dc3e7047a01bdda"
            },
            "downloads": -1,
            "filename": "cloudstile-2.0.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "c29cd096ce3f0fa576384c794b6d32d7",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4.0,>=3.9",
            "size": 7884,
            "upload_time": "2025-07-26T07:44:20",
            "upload_time_iso_8601": "2025-07-26T07:44:20.417459Z",
            "url": "https://files.pythonhosted.org/packages/1f/57/a38c2b3604088bff2b824c049e7948b199e2e97b6d3ed461cd8baaf8cad9/cloudstile-2.0.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "821bc7c93a5923b827e4ce9b2df0066afeae56513b8e3391587c7b7398fd3659",
                "md5": "def13726a975046f8437e5dc6670dc93",
                "sha256": "7ebe6d1caf7e3a840301f8fe06d3f1a888cf05d96c043522f008b02771397805"
            },
            "downloads": -1,
            "filename": "cloudstile-2.0.1.tar.gz",
            "has_sig": false,
            "md5_digest": "def13726a975046f8437e5dc6670dc93",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4.0,>=3.9",
            "size": 4654,
            "upload_time": "2025-07-26T07:44:21",
            "upload_time_iso_8601": "2025-07-26T07:44:21.665969Z",
            "url": "https://files.pythonhosted.org/packages/82/1b/c7c93a5923b827e4ce9b2df0066afeae56513b8e3391587c7b7398fd3659/cloudstile-2.0.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-26 07:44:21",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "notaussie",
    "github_project": "cloudstile",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "cloudstile"
}
        
Elapsed time: 1.99384s