You have a .bin file, an ESP32 board and a USB cable, and every guide quietly assumes you already know where that file goes. So the tool answers Failed to connect to ESP32: Timed out waiting for packet header — or worse, it flashes cleanly to 100% and the board drops into a boot loop. Neither is bad luck. The Flash Download Tool does exactly what you tell it, including writing the right file to the wrong address. Here’s the official build, the offsets that actually work, and the handful of errors worth recognising on sight.
⬇ ESP32 Flash Download Tool 3.9.11 (official Espressif build)
Download Flash Download Tool 3.9.11
Unmodified build pulled straight from Espressif’s own download server — MD5 72713e571a3115c91e89ee0320f6e186, byte-identical to theirs. One executable inside the ZIP. Extract it and run it; nothing is installed on your PC.
What this tool is for, and when to use something else
The Flash Download Tool is Espressif’s Windows GUI for writing raw binaries to the SPI flash of an ESP chip over the serial port. It is not a compiler and not an IDE. It takes files you already have and puts them at addresses you specify.
That makes it right for three jobs: you were handed pre-built firmware and no source; you’re restoring a board to stock after a bad update; or you’re programming one image into a batch of boards. If you’re writing your own code, the Arduino IDE and ESP-IDF already flash for you and you’ll never open this tool.
First run: chip type, work mode, COM port
Extract the ZIP to a short, plain path — C:esp is ideal. Running it from inside the ZIP, from Downloads with a long path, or from a folder with accented characters in the name makes the tool misbehave in ways that look like hardware faults.
Launch flash_download_tool_3.9.11.exe and a small selector appears first:
- ChipType — pick your exact part. ESP32 and ESP32-S3 are not interchangeable here; the tool changes its defaults and its offsets based on this;
- WorkMode — Develop for one board on the bench. Factory is the production layout that drives several COM ports at once from one saved recipe;
- LoadMode — leave it on UART unless you know you’re flashing over the chip’s native USB peripheral.
The main window follows. Down the right side you’ll find the COM port dropdown and the baud rate. If no COM port is listed at all, stop — that’s a driver problem, not a flashing problem, and it’s covered further down.
The offsets, because this is where flashes go wrong
Each row in the file list is a binary plus the address it gets written to. Get an address wrong and the tool still reports success; the chip just has nothing valid to boot. The critical detail almost nobody mentions: the bootloader offset is not the same on every ESP32 variant.
| ESP32, ESP32-S2 | bootloader.bin → 0x1000 |
| ESP32-S3, C2, C3, C6, H2 | bootloader.bin → 0x0 |
| ESP8266 | bootloader / boot.bin → 0x0 |
| All variants | partition-table.bin → 0x8000 |
| All variants | your application .bin → 0x10000 (default single-app layout) |
| Arduino IDE exports | boot_app0.bin → 0xe000 |
| OTA-capable builds | ota_data_initial.bin → 0xd000 |
Two shortcuts save you from the table entirely. If your build system printed a flash command, the offsets are already in it — copy them verbatim. And if you were handed one large merged binary instead of a set of files, it already contains the bootloader and partition table at their correct positions inside it, so it goes to 0x0 alone, with nothing else ticked. Flashing a merged image at 0x10000 is one of the most common ways to brick an evening.
Tick the checkbox left of each row you actually want written; unticked rows are ignored.
SPI speed, SPI mode and flash size
SPI SPEED — 40 MHz is the safe universal answer. 80 MHz works on most modern modules and buys you nothing on a one-off flash.
SPI MODE — DIO is the compatible default and what the vast majority of ESP32 modules want. QIO is faster, but only on modules wired for it; guessing QIO on a DIO module gives you a board that flashes fine and boots to garbage.
FLASH SIZE — match the module, not your hopes. A plain ESP32-WROOM-32 is 4 MB, listed here as 32 Mbit. Declaring more flash than the chip has leads straight to the MD5 error below.
DoNotChgBin — unticked, the tool patches the flash mode, size and frequency bytes in the bootloader header to match the settings above. Tick it only when restoring an exact dump that must not be modified.
Getting the board into download mode
Most dev boards handle this automatically — the tool toggles DTR and RTS, the board resets into the ROM bootloader, and you see nothing. Bare modules, custom boards and a surprising number of cheap clones need it done by hand:
- Hold BOOT (GPIO0 pulled to GND) down;
- Tap EN / RST and release it;
- Release BOOT;
- Click START in the tool.
The board stays in download mode until it’s reset, so there’s no rush between step 3 and step 4. When the write finishes, press EN once to boot the new firmware — the tool does not reset the board for you.
When it fails
No COM port in the dropdown. Windows hasn’t got a driver for the USB-serial chip on the board. Which chip depends on the board: most ESP32 dev boards use a CH340, the official Espressif DevKitC uses a CP2102, better clones use an FT232R, and older ones carry the troublesome PL2303. Install the right one and the port appears. Do not run Zadig on a USB-serial adapter — it will replace a working driver with one that gives you no COM port at all.
“Timed out waiting for packet header” or “Wrong boot mode detected”. The chip isn’t in download mode. Do the BOOT/EN sequence by hand, then retry. If manual entry also fails, suspect the cable — a charge-only USB cable is the single most common false alarm on any bench — and drop the baud rate to 115200.
“MD5 of file does not match data in flash”. The write happened but read-back disagreed. In order of likelihood: the declared flash size is bigger than the real chip; the baud rate is too high for that USB-serial chip (921600 is unreliable on many CH340 clones — 460800 or 115200 is fine); a marginal cable or unpowered hub; or genuinely worn flash on a board that’s been reprogrammed thousands of times.
Flashes to 100%, board boot loops. Nothing is wrong with the tool. It’s an offset or an SPI mode problem — re-check the bootloader address for your exact variant against the table above, and try DIO if you used QIO. Press ERASE first, then flash again, to rule out leftovers from the previous firmware in NVS.
The tool crashes on launch, or opens with garbled settings. Its saved configuration is corrupt. Close it, delete the configure folder next to the executable, and start it again — it rebuilds the folder with defaults. Same fix if a previous session left it convinced you have a chip you don’t.
Your antivirus quarantines the executable. A packaged Python GUI that talks to serial ports and writes firmware trips heuristic scanners regularly. The MD5 published in the download box above is your check: it matches Espressif’s own file exactly.
Factory mode and flashing several boards at once
Develop mode expects you to pick files every session. Factory mode is the other half of the tool and it earns its keep even on small runs: point it at a folder of binaries once and it drives up to eight COM ports at the same time from a single START, giving the operator a green or red bar per port and no chance to type an address wrong.
Tick LOCK SETTINGS after your first successful flash. It freezes the offsets and SPI parameters so a stray click can’t move a file to a new address halfway through a batch.
FAQ
Is this the official tool? Yes. It’s Espressif’s own Flash Download Tool, and the copy here came directly from their download server — the MD5 in the box above proves the file is unchanged. No installer, no bundled extras, no signup.
Does it run on macOS or Linux? No, it’s Windows-only, and it needs no Python — the executable is self-contained. esptool.py is the cross-platform equivalent and speaks the identical protocol, so every offset here transfers directly. Our esptool step-by-step guide covers the v5 command names and the bootloader offset for each chip.
Which flash size should I choose if I don’t know the module? Look at the marking on the metal shield can — WROOM-32 and WROOM-32D are 4 MB (32 Mbit), WROVER modules are usually 4 or 8 MB plus PSRAM. If you can’t read it, flash at 4 MB; under-declaring is harmless, over-declaring is not.
Do I have to erase before flashing? Not normally — writing overwrites what it touches. Erase when you’re changing partition layouts, chasing stale Wi-Fi credentials stored in NVS, or troubleshooting a board that boot loops after an otherwise clean flash.
Can I pull the existing firmware off a board with it? The GUI is built around writing. For a full dump, esptool read-flash 0 ALL backup.bin (formerly esptool.py read_flash) is the dependable route. And if the board is dead enough that it won’t talk over serial at all, the flash die inside the shield can is an ordinary SPI chip — desolder it and read it with a CH341A or an RT809H like any other BIOS chip.
Why does the window freeze after I press START? It doesn’t — a multi-megabyte write at 115200 baud takes a while and the GUI stops repainting. Watch the progress bar, not the title bar.
Is 921600 baud safe? On a CP2102 or FT232R, generally yes. On CH340 clones it’s the leading cause of MD5 mismatches. If a flash fails once at high speed, drop to 460800 before you suspect anything else.
Verdict
The Flash Download Tool is blunt, ugly and completely dependable — it writes the bytes you point it at, to the address you type, and never second-guesses you. That’s precisely why it fails for beginners: it assumes you know the offsets, and the bootloader address moved between ESP32 generations without much fanfare. Get the chip type, the offsets and DIO mode right and it works on the first try, every time.
Keep the ZIP in your tools folder next to the USB-serial drivers, because on a real bench you need both. And if your work drifts from flashing modules over serial towards reading chips off dead boards, that’s a different class of hardware entirely — the CH341A for cheap SPI work, or the TL866II Plus when you want a programmer that verifies properly.
