django-axes for Django Login Attempt Blocking
Keep track of failed login attempts in Django-powered sites.
At a glance
- What is it?
- django-axes is a MIT-licensed Django plugin that records suspicious login attempts and blocks further attempts after a configured limit. It suits application teams needing database or cache-backed protection based on IP address, username, user agent, or combinations.
- Who is it for?
- django-axes is a suitable choice for Django sites that need application-level failed-login tracking and configurable lockout behavior, especially teams prepared to operate migrations, cache services, and authentication configuration. It is a poor fit for sites that require documented user-notification workflows, distributed policy controls, or evidence that a login attempt was successful before blocking.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 10 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What django-axes Protects
django-axes addresses a specific authentication problem: repeated failed login attempts against a Django-powered website. The README describes it as a plugin for tracking suspicious login attempts and implementing simple brute-force attack blocking. It is intended for teams operating Django sites where password authentication needs an application-level counter and a rule that stops further login attempts after a configured limit. The package metadata identifies developers and system administrators as its intended audience. This is not a general identity provider, password policy engine, or replacement for Django's authentication framework. It works alongside that framework and adds observation and blocking behavior around login attempts. The project supports tracking by IP address, username, user agent, or combinations of those values. That choice matters because a site may need to limit one account, one network location, one client type, or several signals together. Axes also documents cool-off periods, IP allowlisting and blocklisting, and user account allowlisting. Those controls indicate an administrative security layer rather than a single unconditional counter. The package is especially relevant to sites exposed to repeated authentication requests, while a site with another authentication architecture may need to evaluate whether its signals can be mapped into Django's login flow.
Database and Cache Tracking Paths
The documented architecture has two persistence choices. Attempts can be persisted in the database indefinitely, or Axes can use a cache implementation described by the README as fast and resistant to DDoS. That choice affects operational behavior, but the README does not define a specific cache backend, cache key format, eviction policy, or replication model. Database storage is the more inspectable option for administrators who need durable records, while cache storage avoids making the database the only path for request-time attempt tracking. Neither choice should be inferred to replace rate limiting at the edge or to guarantee protection against a distributed attack. Axes records attempts and prevents further attempts when the configured limit is exceeded. The README names the relevant signals as IP address, username, user agent, and combinations. It does not describe the internal middleware, signal handlers, model names, or exact request-to-counter sequence, so those implementation details cannot be confirmed from the available documentation. Based on the repository layout, the plugin is contained in the axes package and is tested through a tests directory, with Django integration represented by the setup configuration and test matrix. That layout supports the conclusion that this is an installable Django application rather than a standalone command-line scanner.
Installing django-axes and Starting Configuration
The README directs users to the official documentation at https://django-axes.readthedocs.io/ for installation and configuration. The package metadata names the distribution django-axes and requires Python 3.10 or later, Django 4.2 or later, and asgiref 3.6.0 or later. The repository's setup.py uses the package name django-axes, so the command matches the declared distribution rather than a guessed executable. The metadata also defines an optional ipware extra, which indicates that client IP handling can require the django-ipware dependency. Do not add that extra unless the deployment configuration needs it. The README does not provide the exact Django settings key, middleware entry, migration command, or authentication-backend change for a first login attempt. Those instructions must come from the linked documentation. The package uses Django migrations and database support in the general sense, but the README does not show concrete migration file names or commands, so this article does not invent them. A first real use therefore begins with installing the package, opening the official installation documentation, and choosing whether attempts should be stored in the database or cache before adding the documented middleware and settings.
Lockout Controls and Configuration Trade-offs
Axes offers more control than a simple failed-password counter, but each control also creates a policy decision. A limit based only on IP address can affect multiple users behind one network. A username-based rule can make an account a target for deliberate lockout. Combining IP address, username, and user agent can narrow that effect, although the README does not state the exact combination syntax or how client-controlled headers are interpreted. Cool-off periods offer a way to revisit blocked attempts after a configured interval, while allowlisting provides an exception path for selected addresses or accounts. Blocklisting supports an explicit denial policy. These features make Axes useful for sites that need operational controls around authentication access, but they also make the configuration a security-sensitive part of the deployment. The README does not document notification emails, administrator review screens, audit exports, automatic unblocking, or a rollback procedure. It also does not claim protection against credential stuffing performed with many unrelated usernames or proxies. Axes should therefore be evaluated as a focused attempt-tracking and blocking component, not as a complete account-security program.
Limitations and the Right Alternative
The clearest limitation is that the README does not document what happens when the cache is unavailable, how state behaves across multiple application instances, or whether administrators receive a report of blocked accounts. It also does not document a safe procedure for recovering from an incorrect allowlist or blocklist rule. The package's optional django-ipware dependency is relevant at the boundary where Django receives client IP information. A deployment behind a reverse proxy can make client address interpretation dependent on the proxy configuration, and the README does not confirm which proxy headers or trusted-hop settings the documentation recommends. For comparison, a conventional rate limiter at the ingress, CDN, or application gateway can reject excessive requests before they reach Django, while django-axes operates inside the Django authentication path and records login-specific signals. A gateway is the better fit when the primary requirement is broad request throttling across many endpoints. django-axes is the better fit when the policy is specifically about Django login attempts, usernames, accounts, or user agents. A full identity platform may be more appropriate when the site needs advanced risk scoring, multifactor authentication, or account lifecycle management, none of which is described by this repository.
Release Support and Upgrade Surface
The repository is not archived, and the last push was on 2026-10-13. Recent releases listed for the project are 8.3.2 on 2026-08-30, 8.3.1 on 2026-02-11, and 8.3.0 on 2026-02-09. The setup metadata declares Python 3.10 or later and Django 4.2 or later, while the tox configuration names test combinations for Django 4.2, 5.2, 6.0, and Django main. That matrix gives engineers a concrete compatibility surface to check during upgrades. The README does not provide a migration guide, upgrade command, or a list of configuration changes between these releases. The package uses setuptools_scm for its version, and the development dependencies include pytest, pytest-django, mypy, prospector, and black. The MIT license permits use and modification under its terms, but license text does not answer operational questions such as whether a particular Django authentication integration is supported. Maintainer information names Jazzband, and the issue tracker is https://github.com/jazzband/django-axes/issues. For an upgrade, the first verification should therefore be compatibility with the deployed Django and Python versions, followed by a review of the release notes and the project's official documentation.
Editorial conclusion
django-axes is a suitable choice for Django sites that need application-level failed-login tracking and configurable lockout behavior, especially teams prepared to operate migrations, cache services, and authentication configuration. It is a poor fit for sites that require documented user-notification workflows, distributed policy controls, or evidence that a login attempt was successful before blocking. Verify first that your Django version, Python version, storage backend, proxy IP detection, and chosen lockout settings match the deployment model, then review the documentation at https://django-axes.readthedocs.io/ before enabling it in production.
Frequently asked questions
How does django-axes block brute-force login attempts?
The README states that django-axes records login attempts and prevents further attempts when the configured attempt limit is exceeded. It can track IP address, username, user agent, or combinations.
Where can django-axes store failed login attempts?
The README says attempts can be persisted in the database indefinitely or stored in a cache implementation described as fast and resistant to DDoS. It does not provide specific cache configuration details.
What Django and Python versions does django-axes require?
The setup.py metadata specifies Python 3.10 or later, Django 4.2 or later, and asgiref 3.6.0 or later. The tox configuration also names test environments for Django 4.2, 5.2, 6.0, and Django main.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/jazzband-django-axes)Was this useful?