
Who Esp32 C3 Adblock is for#
Home network ad blocking on a budget
Point your router or devices at the board's IP, or add it as a secondary resolver behind your main DNS, to block ad domains for the whole household.
Skip if:
You need regex or wildcard filtering, per-user policies, or an encrypted DNS endpoint.
Plug-in blocker for a router's USB port
Power the board from the router's spare USB port using a USB-A to USB-C dongle, with no extra power supply or box.
Skip if:
Your router has no USB port and you have no stable USB power source nearby.
Embedded and DNS tinkering
The hash-in-flash design is documented in the README and the code is MIT, which makes it a good base for learning how a UDP DNS sinkhole works on constrained hardware.
Skip if:
You want a finished appliance with no firmware building and flashing.
The problem it solves#
Blocking ads at the DNS level normally needs an always-on computer such as a Raspberry Pi running Pi-hole, or a paid hosted resolver like NextDNS or AdGuard DNS. Existing ESP32 sinkholes keep blocklist domain strings in RAM, which pushes you to a pricier board with PSRAM. If you want a small, cheap device that plugs into a router's USB port and filters every device on the network, those options are either too heavy or too costly.
How it solves it#
Hash table in flash
Domains are stored as sorted 5-byte FNV-1a hashes in flash and found by binary search, so no blocklist lives in RAM. The README reports 140,000+ domains in about 0.7 MB of flash and about 50 KB of RAM.
Web dashboard
The dashboard at c3adblock.local shows per-client block and allow counts, lets you ban a client, and lets you add custom blocked domains. State-changing endpoints require HTTP Basic Auth.
Over-the-air updates
Upload a new blocklist.bin or firmware image from the dashboard, or set a URL for scheduled remote blocklist pulls. A default list is rebuilt every Monday by GitHub Actions and published at a stable release URL.
Flexible blocklist builder
tools/build_blocklist.py accepts hosts files, plain domain lists, and AdGuard or Adblock basic rules, from URLs or local files. A blocked domain also blocks its subdomains. The default is StevenBlack base plus Hagezi Light.
Captive-portal WiFi setup
If the board cannot connect, it starts an open access point named C3-AdBlock-XXXX with a setup portal, so you can pick a network from a phone without re-flashing. The Forget WiFi button or holding BOOT at power-on brings the portal back.
Strengths and trade-offs#
Strengths
- Very low hardware costIt runs on an ESP32-C3 with 4 MB flash and no PSRAM, which the README prices at about $2. A USB-A to USB-C dongle lets it draw power from the spare USB port on most routers.
- Fast lookups on tiny memoryA lookup takes about 18 flash reads, roughly 10 ms including WiFi round trip according to the README. RAM use stays around 50 KB.
- Updates without a USB cableAfter the one USB flash, both firmware and blocklist update over WiFi, including a scheduled pull of a prebuilt list.
- Permissive MIT licenseThe code is MIT licensed, so you can modify the firmware and the hash-building script for your own network.
Trade-offs
- -Limited blocklist size with firmware OTAFirmware OTA needs two app slots, which leaves about 1.3 MB for the blocklist, around 250k domains at most. The 537k-domain list only fits the single-app partition table, which gives up firmware OTA.
- -Plain HTTP dashboardThe dashboard runs over HTTP on port 80 with no TLS. Basic Auth credentials are base64, so someone sniffing your LAN can read them. The setup portal access point is also open by design.
- -Credentials must be set by youWEB_USER, WEB_PASS, and OTA_PASS in secrets.h are required. If the placeholder values remain, the device still boots and the placeholders are public in the repo.
- -DNS blocking only, with hash collisionsRegex, wildcard, modifier, and cosmetic rules are skipped. At 537k domains the README expects about one hash collision, which over-blocks one domain. Only the C3 is a tested target.
Esp32 C3 Adblock vs alternatives#
Esp32 C3 Adblock vs NextDNS
NextDNS is a paid hosted DNS filtering service. Esp32 C3 Adblock is firmware you flash onto your own board, so DNS queries are answered on your network by a device you control. The trade is capability: this project blocks by domain hash list, and it skips regex, wildcard, and cosmetic rules. It has no TLS on its dashboard, and its list tops out around 250k domains with firmware OTA enabled.
Choose NextDNS if you need a managed service that works outside your home network. Choose this project if you want a local, low-cost blocker and are comfortable flashing firmware.
Esp32 C3 Adblock vs AdGuard DNS
AdGuard DNS is also a paid hosted resolver. The ESP32 firmware can build its blocklist from AdGuard or Adblock basic rules, including @@ allow rules, so you can mirror part of an existing list. Rules a hash list cannot express are skipped and counted during the build.
Where it fits
It suits a single home network where one cheap device can sit behind the router. It does not replace a managed resolver for roaming devices or per-user policies.
Quick start#
Install uses PlatformIO to flash the board once over USB, then the web dashboard handles updates.
```bash
git clone https://github.com/M-Abozaid/esp32-c3-adblock
cd esp32-c3-adblock
cp src/secrets.example.h src/secrets.h
python3 tools/build_blocklist.py data/blocklist.bin
pio run -t upload
pio run -t uploadfs
```What it's built on#
- Languages
- CC++Python
FAQ#
Does it need PSRAM?
No. It targets an ESP32-C3 with 4 MB flash and no PSRAM, because the blocklist lives as hashes in flash rather than strings in RAM. A classic ESP32 with 4 MB also builds, though that target is community-contributed and only compile-tested.
How many domains can it block?
The README reports 140,000+ domains in about 0.7 MB of flash. With firmware OTA enabled, the 4 MB flash layout holds about 250k domains. The 537k-domain list needs the single-app partition table, which removes firmware OTA.
How do I install it?
Copy src/secrets.example.h to src/secrets.h and set real WEB_USER, WEB_PASS, and OTA_PASS values. Build the blocklist with tools/build_blocklist.py, then flash with PlatformIO using pio run -t upload and pio run -t uploadfs. Use a current PlatformIO, since the old apt version fails.
Is it safe to use on my network?
Mutating endpoints need Basic Auth and a custom X-Requested-With header, which hardens against casual LAN access and CSRF. It is plain HTTP, so it does not defend against an on-path attacker. Set real credentials before trusting it.
What license does it use?
The project is MIT licensed, as shown in the repository's LICENSE file and GitHub metadata.
Similar open-source tools#
Obtainium
Android app updates direct from GitHub and F-Droid
tailcat
Encrypted tunnels between machines, no account or IP needed
hysteria
Fast and censorship-resistant proxy solution
Cloudflare Os
Open source AI workspace with sandboxed apps and Gatekeeper security
OpenShell
Sandboxed runtime for autonomous AI agents, open source by NVIDIA
openbao
Open source secret management governed by the Linux Foundation

