django/daphne: the ASGI server behind Django Channels
Django Channels HTTP/WebSocket server
At a glance
- What is it?
- Daphne terminates HTTP, HTTP/2 and WebSocket connections for ASGI applications. It is the reference server shipped with Django Channels, and its README is honest about what it does not do.
- Who is it for?
- Adopt daphne if you are running Django Channels and want the server the Channels project itself develops, or if you need one process to negotiate HTTP and WebSocket traffic on the same port without URL prefixing. Do not adopt it if you want a general-purpose production front end with process supervision, static file serving and mature HTTP/2 features; put a reverse proxy in front instead, or use a different server.
- Can I use it commercially?
- Yes. BSD-3-Clause 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 33 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 September 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem daphne solves: one port for HTTP and WebSocket
A conventional WSGI server speaks request and response. WebSockets need a connection that stays open and switches protocol mid-stream, and the WSGI interface has no place to put that. Daphne implements the ASGI and ASGI-HTTP specifications, which describe both shapes of traffic in one interface, so a single process can accept a browser's HTTP request and the same browser's WebSocket upgrade on the same port.
The README makes the practical consequence explicit: daphne supports automatic negotiation of protocols, and there is no need for URL prefixing to determine WebSocket endpoints versus HTTP endpoints. That matters when you are building a Django application where a page and its live channel live under the same hostname and the same routing table. You do not have to decide at the proxy layer which paths are sockets and which are pages.
The audience is narrow and identifiable. This is for people deploying Django Channels, or any other ASGI application, who need a server that speaks the protocol the framework expects. It is not a general web server with a module ecosystem, and the README does not present it as one.
How daphne handles a connection, from socket to ASGI callable
The architecture is visible in the packaging. The project depends on Twisted, autobahn and asgiref, and the built distribution maps a twisted package directory inside the daphne source tree, which is how daphne ships its Twisted protocol implementations. Twisted owns the sockets and the reactor; autobahn supplies the WebSocket protocol handling; asgiref is the bridge that turns protocol events into ASGI messages for your application.
The entry point is a console script declared in pyproject.toml as daphne.cli:CommandLineInterface.entrypoint, so the command you run and the Python function it calls are the same thing. You hand that command an import path to an ASGI callable, and daphne builds a server around it.
Binding is more flexible than a single host and port. The README documents a bind address and port, a UNIX socket via -u, a file descriptor inherited from a process manager via --fd, and Twisted endpoint description strings via --endpoint or -e, which can be repeated. That last option is where TLS and, by extension, HTTP/2 come from: you describe an ssl endpoint and daphne terminates TLS itself.
Installing daphne and running your first ASGI application
Daphne is distributed on PyPI, and the README assumes an existing Django project with an ASGI module. Install the package first.
pip install daphneThen point the server at your ASGI callable. The README's example uses a bind address of 0.0.0.0 and port 8001; with no flags at all it defaults to localhost on port 8000.
daphne -b 0.0.0.0 -p 8001 django_project.asgi:applicationIf daphne sits behind a proxy, the README offers a UNIX socket instead of a TCP port, which avoids exposing a listening port to anything but the proxy.
daphne -u /tmp/daphne.sock django_project.asgi:applicationFor a process manager that hands down a socket, daphne can bind to an inherited file descriptor. The README's example uses descriptor 5.
daphne --fd 5 django_project.asgi:applicationTo see every option, run the command with -h. One deployment detail is easy to miss: if your application is mounted under a subpath, daphne sets the root path either from the --root-path option or from a Daphne-Root-Path header, and the README states the header takes precedence and is not passed down to the application. The value is URL-encoded ASCII, starts with a slash and does not end with one.
daphne --root-path=/forum django_project.asgi:applicationPython 3.10 or later is required, per both the README and the requires-python field in pyproject.toml.
HTTP/2 in daphne requires TLS, OpenSSL and two Twisted extras
HTTP/2 termination is built in, but it does not work by default. The README lists three conditions. You install the Twisted tls and http2 extras, you start daphne with TLS enabled, and the host has OpenSSL 1.0.2 or greater.
pip install -U "Twisted[tls,http2]"TLS is configured through the endpoint syntax, with a private key and certificate file. The README's example binds port 443 and notes that pyopenssl must be installed for this to work.
daphne -e ssl:443:privateKey=key.pem:certKey=crt.pem django_project.asgi:applicationWhen it is working, the startup log states that HTTP/2 support is enabled. The README also warns that the log is otherwise indistinguishable from an HTTP/1.1 run, and that browser network inspectors rarely make the protocol obvious, so verifying it takes a browser extension or an external check.
The feature boundary is stated plainly: daphne supports normal requests over HTTP/2 only, with no Server Push. And if a reverse proxy sits in front of daphne, HTTP/2 reaches your users only when that proxy understands and passes the connection through correctly. That is a real constraint on the common deployment shape where daphne is not the public-facing process.
Where daphne is the wrong tool
The README documents no process management, no worker model, no static file serving and no configuration file. Everything is command line flags or a header. If you need a server that forks workers, reloads on code change, serves your static assets and reads a config file, daphne does none of that, and the project does not claim otherwise.
HTTP/2 is the sharpest limitation. Because browsers only negotiate HTTP/2 over TLS, and because daphne's HTTP/2 support excludes Server Push, a deployment that terminates TLS at a load balancer gets no HTTP/2 benefit from daphne at all. The README says as much when it notes that the protocol only works if the proxy in front passes the connection through correctly. In that topology daphne is doing HTTP/1.1 work behind a proxy that owns the interesting protocol.
The project's own metadata is worth reading before you commit. The classifier in pyproject.toml reads Development Status :: 4 - Beta. Whatever the project's release history looks like, that is the status it publishes about itself.
Security reports go to [email protected] rather than the public issue tracker. That is a process fact, not a limitation, but it changes how you report a problem you find.
daphne compared with uvicorn
The obvious alternative for running an ASGI application is uvicorn, which is not part of this repository and is not described in it. The difference in approach is worth stating precisely, because it determines which one fits your deployment.
Daphne is built on Twisted and autobahn, and it ships the protocol implementations inside its own package tree, which is why the packaging maps a twisted directory into the distribution. Uvicorn is built on asyncio and httptools or h11, with a separate optional worker manager. Daphne's binding options reflect the Twisted model: endpoint description strings, UNIX sockets, inherited file descriptors, and TLS terminated inside the process. Uvicorn's reflect a simpler model of host, port and worker count.
The practical split is this. If your stack is Django Channels and you want the server maintained alongside the Channels project, with the same contributing process, daphne is the coherent choice. If you want a lean ASGI server with a worker manager and no Twisted in your dependency graph, uvicorn is the one to evaluate. Both implement ASGI; the choice is about the surrounding machinery, not the interface your application sees.
Maintenance, licence and what upgrading costs you
Daphne is BSD-3-Clause licensed, and pyproject.toml declares the licence as BSD with the OSI Approved :: BSD License classifier. That is a permissive licence, which in practice means you can ship it inside a commercial product without publishing your own source. This is a description of the licence text, not legal advice; check the LICENSE file and your own obligations.
The repository is not archived, and the last push was on 2026-08-28, which is recent enough that the project is being touched. The README points contributors at the Channels contributing documentation, and the maintenance team is described in the main Channels readme rather than here, so governance lives one level up from this repository.
Upgrade cost is dominated by the dependency floor, not by daphne's own API. The declared dependencies are asgiref>=3.5.2,<4, autobahn>=22.4.2 and twisted[tls]>=22.4, and requires-python is >=3.10. The upper bound on asgiref is the one to watch: it is pinned below version 4, so a future asgiref major release will require a coordinated upgrade. Twisted and autobahn carry their own release cadences, and the HTTP/2 path additionally depends on the tls and http2 extras plus OpenSSL 1.0.2 or greater on the host. If you run daphne in containers, that OpenSSL floor is part of your base image decision.
The repository has no release notes in what is published here, but it does publish a CHANGELOG.txt at the top level and links to it from pyproject.toml. Read that file before upgrading rather than inferring changes from version numbers.
Editorial conclusion
Adopt daphne if you are running Django Channels and want the server the Channels project itself develops, or if you need one process to negotiate HTTP and WebSocket traffic on the same port without URL prefixing. Do not adopt it if you want a general-purpose production front end with process supervision, static file serving and mature HTTP/2 features; put a reverse proxy in front instead, or use a different server. Before committing, verify two things in your own environment: that your Python is 3.10 or later, and that your deployment path can supply TLS, because HTTP/2 negotiation in daphne only happens over TLS.
Frequently asked questions
How do I install daphne?
Install it from PyPI with pip, then run the daphne console script against your ASGI callable. Daphne requires Python 3.10 or later.
How do I use daphne in Django?
Point the daphne command at your project's ASGI application, for example django_project.asgi:application, and optionally set a bind address and port. It defaults to localhost on port 8000.
How do I use daphne?
Run the daphne command with an import path to an ASGI application. The README documents bind address and port flags, a UNIX socket option, an inherited file descriptor option, and repeatable Twisted endpoint strings for more control.
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/django-daphne)