Skip to main content

User Agent integration for ASGI applications.

Project description

asgi-user-agents

CI Coverage PyPI - Version PyPI - Python Version License Latest Commit

Downloads Downloads/Month Downloads/Week

User Agents integration for ASGI applications. Works with Starlette, FastAPI, Quart, Litestar -- or any other web framework supporting ASGI that exposes the ASGI scope.


Table of Contents

Installation

NOTE: This is alpha software. Please be sure to pin your dependencies.

Latest Release

pip install asgi-user-agents

Development Version

pip install git+https://github.com/hasansezertasan/asgi-user-agents.git

How does it work?

It simply adds a ua attribute to the request scope. This attribute is an instance of the UADetails class which abstracts the UserAgent class from the user-agents package 📄.

Usage

It's pretty simple. Just add the middleware to your ASGI application and access the ua attribute from the request scope.

from asgi_user_agents import UAMiddleware
from asgi_user_agents import UARequest as Request
from fastapi.applications import FastAPI
from starlette.middleware import Middleware
from starlette.responses import JSONResponse, Response


app = FastAPI(middleware=[Middleware(UAMiddleware)])


@app.get("/")
async def index(request: Request) -> Response:
    ua = request.scope["ua"]
    data = {
        "ua_string": ua.ua_string,
        "os": ua.os,
        "os.family": ua.os.family,
        "os.version": ua.os.version,
        "os.version_string": ua.os.version_string,
        "browser": ua.browser,
        "browser.family": ua.ua.browser.family,
        "browser.version": ua.ua.browser.version,
        "browser.version_string": ua.ua.browser.version_string,
        "device": ua.device,
        "device.family": ua.device.family,
        "device.brand": ua.device.brand,
        "device.model": ua.device.model,
        "is_provided": ua.is_provided,
        "is_tablet": ua.is_tablet,
        "is_mobile": ua.is_mobile,
        "is_touch_capable": ua.is_touch_capable,
        "is_pc": ua.is_pc,
        "is_bot": ua.is_bot,
        "is_email_client": ua.is_email_client,
    }
    return JSONResponse(data)

Framework integrations

For Litestar and FastAPI, optional contrib subpackages provide framework-idiomatic access. The core UAMiddleware still works for any ASGI framework — contrib is additive convenience.

Install with the relevant extra:

pip install asgi-user-agents[litestar]
pip install asgi-user-agents[fastapi]

Litestar

Use UAPlugin to inject ua: UADetails and user_agent: UserAgent into route handlers. No middleware needed.

from litestar import Litestar, get

from asgi_user_agents import UADetails
from asgi_user_agents.contrib.litestar import UAPlugin


@get("/")
async def index(ua: UADetails) -> dict:
    return {"is_bot": ua.is_bot, "browser": ua.browser.family}


app = Litestar(route_handlers=[index], plugins=[UAPlugin()])

If you already registered a dependency named ua or user_agent, UAPlugin will not overwrite it.

FastAPI

Use install_ua(app) plus the prebuilt UADep / UserAgentDep annotated dependencies.

from fastapi import FastAPI

from asgi_user_agents.contrib.fastapi import UADep, install_ua

app = install_ua(FastAPI())


@app.get("/")
async def index(ua: UADep) -> dict:
    return {"is_bot": ua.is_bot, "browser": ua.browser.family}

install_ua is idempotent. The plain dependency functions get_ua and get_user_agent are also exported if you prefer to wire them yourself.

API Reference

UAMiddleware

An ASGI middleware that sets scope["ua"] to an instance of UADetails (scope refers to the ASGI scope).

app = UAMiddleware(app)

UADetails

A helper that provides shortcuts for accessing User-Agent request header.

ua = UADetails(scope)
  • ua: UserAgent - The UserAgent instance from the user-agents package.
  • ua_string: str - The user agent string.
  • is_provided: bool - True if the user agent string is provided.
  • os: OperatingSystem - The operating system details of the user agent. It's a named tuple with the following fields:
    • family: str - The family of the operating system.
    • version: str - The version of the operating system.
    • version_string: str - The version of the operating system as a string.
  • browser: Browser - The browser details of the user agent. It's a named tuple with the following fields:
    • family: str - The family of the browser.
    • version: str - The version of the browser.
    • version_string: str - The version of the browser as a string.
  • device: Device - The device details of the user agent. It's a named tuple with the following fields:
    • family: str - The family of the device.
    • brand: str - The brand of the device.
    • model: str - The model of the device.
  • is_tablet: bool - True if the request was made by a tablet.
  • is_mobile: bool - True if the request was made by a mobile device.
  • is_touch_capable: bool - True if the request was made by a touch-capable device.
  • is_pc: bool - True if the request was made by a PC.
  • is_bot: bool - True if the request was made by a bot.
  • is_email_client: bool - True if the request was made by an email client.

UARequest

For Starlette-based frameworks, use this instead of the standard starlette.requests.Request so that code editors understand that request.scope["ua"] contains an UADetails instance:

from asgi_user_agents import UARequest as Request

async def home(request: Request):
    reveal_type(request.scope["ua"])  # Revealed type is 'UADetails'

Development

Clone the repository and cd into the project directory:

git clone https://github.com/hasansezertasan/asgi-user-agents
cd asgi-user-agents

Install hatch, you can follow the instructions, or simply run one of the following commands:

mise use hatch
uv tool install hatch
pipx install hatch

The commands below can also be executed using the xc task runner, which combines the usage instructions with the actual commands. Simply run xc, it will popup an interactive menu with all available tasks.

env

Initialize the environment and install the dependencies:

hatch shell

hooks

Initialize pre-commit hooks by running the following command:

pre-commit install

test

Make your changes on a new branch and run the tests:

hatch test -a

types

Make sure that the code is typed, linted, and formatted correctly:

hatch run types:all

co

Stage your changes and commit them:

Inputs: MESSAGE

git add .
git commit -m "$MESSAGE"

pr

Create a pull request and wait for the review 🤓.

gh pr new -B main

Author

Credits

  • This project wouldn't be possible without the user-agents package 🙏.
  • The project structure is inspired by the asgi-htmx 🚀 package and contains some code snippets from it 😅 (even this file).

Analysis

License

asgi-user-agents is distributed under the terms of the MIT license.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

asgi_user_agents-0.3.0.tar.gz (71.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

asgi_user_agents-0.3.0-py3-none-any.whl (11.5 kB view details)

Uploaded Python 3

File details

Details for the file asgi_user_agents-0.3.0.tar.gz.

File metadata

  • Download URL: asgi_user_agents-0.3.0.tar.gz
  • Upload date:
  • Size: 71.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for asgi_user_agents-0.3.0.tar.gz
Algorithm Hash digest
SHA256 30ef233cfb7fec27f8465be1e91e360358a3db08112fd4a10dd0daf755a6c9a8
MD5 9fd9efbb97d10846be22c5a16270ed3e
BLAKE2b-256 d1bd70757a7ecd8750a370a4480502ae53738ac880c1e7f2d08333f92b43df1f

See more details on using hashes here.

File details

Details for the file asgi_user_agents-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: asgi_user_agents-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 11.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for asgi_user_agents-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 882472eeb1cef16732a0e0d623a8e13c5d714aca3597059a729443e324cef078
MD5 4d8949ccc337f07e4281659bfea73188
BLAKE2b-256 79afac5bdbd3bffd2cd9f46b5f4c8e49714be8055577ea50f8e3e6ba2ff9a8ba

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page