gfwlist/gfwlist: the upstream rule list behind most China proxy setups
The one and only one gfwlist here
At a glance
- What is it?
- gfwlist is a plain-text domain list that proxy clients consume to decide what to route. The repository is a data file with a submission process, not software, and that shapes everything about how you use it.
- Who is it for?
- Adopt gfwlist if you run a proxy client that accepts a remote rule URL and you want a maintained domain list without writing one yourself. Do not adopt it if you need per-request policy, application-aware routing, or a list you can audit line by line for a compliance review: the file is large, community-sourced, and changes without notice.
- Can I use it commercially?
- Yes, with conditions. LGPL-2.1 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- GitHub does not report a main language for this repository.
Answers come from the project's GitHub data, last synced on September 28, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What gfwlist actually is: a data repository, not a program
The repository description is blunt: "The one and only one gfwlist here." There is no daemon, no CLI, and no configuration format of its own. The top level holds gfwlist.txt, a list.txt, a COPYING.txt under LGPL-2.1, a .gitmodules file, and an apollyon directory that the README points to as the maintenance tooling. If you came looking for a binary to install, you are in the wrong repository. What you get is a text file that other programs read.
That distinction matters for evaluation. You are not adopting a runtime; you are adopting a data source and the process that produces it. The README describes that process: users report new URLs, the maintainers run availability testing before adding them, and the README states plainly that there is no real-time update for submitted URLs. So the list is curated rather than scraped continuously, and the latency between a site being blocked and appearing in the file is a property of the project, not a bug you can configure away.
Who this is for: people running a proxy client that supports remote rule subscriptions, and developers who need a domain corpus to feed into their own routing logic. Who it is not for: anyone who wants a self-contained censorship-circumvention tool. gfwlist routes nothing by itself.
How gfwlist.txt travels from repository to proxy client
The data flow is short. A maintainer or contributor edits the list, the change lands on master, a CDN picks it up, and your client polls the CDN URL and replaces its local copy. The README lists several subscription addresses and explicitly recommends the CDN mirrors because the raw GitHub URL can be unreachable from parts of mainland China. The recommended ones are on jsDelivr, with gcore, testingcf and Fastly variants, plus a GitLab mirror and a repo.or.cz mirror that the README itself flags as possibly out of sync or slow from both inside and outside the country.
The file is not a plain newline-delimited domain list in the obvious sense. Clients that support gfwlist expect the base64-encoded AutoProxy format, which is why the same URL works across Shadowrocket, SwitchyOmega, Clash-style converters and dnsmasq rule generators. That encoding is also why the list is awkward to inspect: you cannot grep it usefully until you decode it. The README does not document the encoding, the format version, or the semantics of the include and exclude directives that the AutoProxy format carries, so anyone building a parser has to rely on the client ecosystem rather than this repository.
The apollyon submodule is the piece that generates and validates the list. Because it is registered as a submodule rather than vendored, a plain clone of gfwlist leaves that directory empty. The README links to the apollyon project page for the source, which is the honest place to look if you want to understand or reproduce the maintenance workflow.
Subscribing to gfwlist in a proxy client or a DNS resolver
The README does not give installation steps, because there is nothing to install. What it gives is the subscription URL, and that is the first real use. The README lists the recommended CDN address for the gcore jsDelivr mirror, which you paste into your client's rule-subscription field:
https://gcore.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txtAfter the client fetches it, the rule list should populate with a large set of domains, and traffic to those domains should follow whatever policy you attached to the subscription. If the list stays empty, the usual cause is that the client expected the decoded form or a different format, not that the URL is wrong.
The README also gives the raw GitHub address, which it notes may be unreachable in parts of mainland China:
https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txtIf you want to inspect the file rather than hand it to a client, you have to decode it first, because the body is base64. The README does not document that step, and it does not document the AutoProxy directives the decoded file contains. For DNS-level setups, the related tooling around this file (dnsmasq, smartdns and similar resolvers) consumes the decoded domains and turns them into address rules; that conversion is done by those tools, not by gfwlist, and the README does not describe it.
One practical constraint: the README's mirror list is not equivalent. The jsDelivr endpoints are the recommended path; the GitLab and repo.or.cz mirrors may lag. If your client polls on a schedule, point it at one CDN host rather than rotating, so you can tell which copy you actually have.
Where gfwlist is the wrong tool
gfwlist is a static domain list, and static domain lists fail in specific, predictable ways. It cannot express per-application policy: the file has no notion of which process made a request, so a client that only understands domain rules will route every request to a listed domain the same way. It cannot match on IP, port, or SNI beyond what the client's own rule engine adds on top. And it cannot react to a domain that is blocked only intermittently or only from certain networks, because membership in the list is binary.
The maintenance model is the second limitation. The README states that submitted URLs go through availability testing before being added, and that there is no real-time update. That is a deliberate quality trade-off, and it means the list lags. If you are testing a newly blocked service today, gfwlist will not know about it. You need a client-side rule you wrote yourself, or a different list with a faster intake.
The third issue is auditability. Because the file is base64-encoded and large, reviewing what it contains is a project in itself. For a personal proxy that is fine. For an organization that has to justify its egress rules, a list you cannot read at a glance is a poor fit, and the README offers no per-line provenance, no changelog in the repository root, and no release artifacts to pin against. There are no published releases at all, so version pinning means pinning a commit hash.
tinylist and apollyon: the two projects gfwlist itself points to
The README recommends two sibling projects, and the difference between them is the useful comparison. tinylist is described as a trimmed version of gfwlist. The approach differs in scope rather than mechanism: same AutoProxy-style consumption, far fewer entries, on the theory that a smaller list reduces false positives and client-side matching cost. If your proxy client struggles with a large rule set, or if you keep hitting domains that are listed but reachable, tinylist is the direct alternative and the README points at it first.
apollyon is the other direction. It is the maintenance tool, and the README links to it for source. Where gfwlist is the artifact, apollyon is the machinery that produces and checks it. If you want to run your own list with your own intake criteria, apollyon is the thing to read, not gfwlist.txt. The trade-off is that you inherit the maintenance burden: the availability testing the README describes is work, and it is the reason the upstream list is not updated in real time.
Neither comparison is about raw capability. All three consume or produce the same kind of data. The choice is about how much of the list you want and how much of the process you want to own.
Licence, maintenance signals, and the cost of staying current
The repository is licensed LGPL-2.1, per COPYING.txt. For a data file this is an unusual choice and worth pausing on: LGPL is a software licence with source and relinking obligations, and it is not obvious how those map onto a list of domains embedded in a client. The README says nothing about how the list may be redistributed inside another product, and it does not offer a separate data licence. If you plan to ship gfwlist.txt or a derivative inside a commercial client, that question needs an answer from the maintainers or a lawyer, not from this article. Nothing here is legal advice.
On maintenance, the last push to the repository was on 2026-09-11, which is recent, and the repository is not archived. That tells you the list is still being edited. It does not tell you how often, and there are no releases to measure cadence against, so the only observable signal is the commit history on master.
The upgrade cost is close to zero by design: clients re-fetch the URL and replace the previous copy. The cost that does not go away is verification. Because there is no versioned release, a regression in the list reaches every subscriber at once, and the only rollback available is pinning a commit hash from the CDN or from git. The README does not document rollback, so plan for it yourself if the list drives production traffic.
Editorial conclusion
Adopt gfwlist if you run a proxy client that accepts a remote rule URL and you want a maintained domain list without writing one yourself. Do not adopt it if you need per-request policy, application-aware routing, or a list you can audit line by line for a compliance review: the file is large, community-sourced, and changes without notice. Before you point a client at it, fetch gfwlist.txt from the jsDelivr mirror, confirm your client parses the base64 body, and check whether tinylist covers your case with far fewer rules. The repository also ships as a git submodule, so a shallow clone is not enough if you want apollyon alongside the list.
Frequently asked questions
What is gfwlist and what do I actually download?
gfwlist is a rule list repository, not a program. The file you consume is gfwlist.txt, which the README distributes through CDN subscription URLs such as the jsDelivr gcore mirror. The README also links to tinylist for a trimmed version and apollyon for the maintenance tooling.
How do I use gfwlist with Shadowrocket, SwitchyOmega or dnsmasq?
You add the subscription URL to the client and let it fetch and parse the list; the README recommends the CDN mirrors because the raw GitHub address can be unreachable from parts of mainland China. For DNS resolvers such as dnsmasq, the conversion from the list into address rules is done by those tools, and the README does not describe that step.
How quickly does gfwlist add a newly blocked site?
The README states that submitted URLs are not updated in real time and that the maintainers usually run availability testing before adding them to the list. Expect a delay between a site being blocked and appearing in gfwlist.txt, and add a local rule in the meantime.
Can I redistribute gfwlist inside my own product?
The repository carries LGPL-2.1 in COPYING.txt, and the README does not explain how that licence applies to redistributing the domain list itself. That question needs an answer from the maintainers or a lawyer rather than from the documentation.
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/gfwlist-gfwlist)