⌁ Embedded & Hardware

ESP32 Web Flasher

Flash ESP32, S2, S3, C3, C6 and H2 firmware from the browser with esptool-js: chip detection, offset presets, overlap and chip-mismatch checks, erase, and MD5 verification.

esptool-js in the browser Offset presets per chip Blocks wrong layouts MD5 verify & reset

Loading ESP32 Flasher…

What this page sends

  • Your input: Firmware files are read locally and written to your board over Web Serial (USB). Nothing is sent to a server; the MD5 check compares a hash computed by the chip with one computed in this tab.
  • Page load: Loading the page requests HTML, scripts and images from ByteKiln, fonts from Google Fonts, and sends Google Analytics page views, tool-usage events and catalog interactions (tool/category IDs, result status and whether a click followed search — never your input, output or search terms). Privacy & sharing

How the ESP32 Web Flasher Works

Flashing an ESP32 usually means installing Python and esptool, or the Arduino IDE, just to write a few files to a board. This page does it from the browser using esptool-js, Espressif's JavaScript port of esptool, over Web Serial. Connect, and it resets the board into the bootloader, identifies the chip (ESP32, S2, S3, C2, C3, C5, C6, H2 or P4), and reads its MAC address, flash size and features. Add one merged .bin or the separate bootloader, partition table, boot_app0 and application files, pick a layout preset, and the offsets are filled in for that chip. Before anything is written, the tool checks every file: overlapping address ranges, files that run past the end of the flash, a bootloader at the wrong offset for the connected chip, and images compiled for a different chip are all blocked with an explanation. Flashing shows progress per file, verifies each region with an MD5 checksum computed by the chip, and hard-resets the board so the new firmware starts. Firmware files are read locally and written to the board over Web Serial; nothing is sent to a server.

Offsets

The second-stage bootloader lives at 0x1000 on ESP32 and ESP32-S2, at 0x0 on ESP32-S3, C2, C3, C6 and H2, and at 0x2000 on ESP32-C5 and P4. The partition table is at 0x8000, Arduino's OTA data (boot_app0.bin) at 0xE000, and the first app partition usually at 0x10000. A merged image already contains everything at the right place and goes at 0x0.

Image checks

ESP images start with the magic byte 0xE9 and an extended header that records the target chip ID. The tool reads it to detect bootloaders, applications and merged images and the chip they were built for; partition tables are recognized by their 0xAA50 magic.

Writing and verifying

esptool-js loads a small flasher stub into the chip's RAM, switches to the chosen baud rate, writes compressed data, and then asks the chip for the MD5 of each written region, which is compared with an MD5 computed locally. After writing, it toggles RTS to reset into the new firmware.

Recovery

Because the ROM bootloader can't be erased, an interrupted flash only leaves invalid data in flash. Holding BOOT while resetting enters download mode again. Boards with native USB (S2, S3, C3, C6) re-enumerate after reset and may appear as a different port.

Limitations

  • Web Serial is required: desktop Chrome, Edge or Opera, not Firefox, Safari or most phones.
  • It writes and erases flash. Reading flash back to a file, eFuse operations, secure boot and flash encryption are not supported — use esptool.py for those.
  • Offsets come from presets or what you type; a wrong offset for a custom partition table will flash successfully and still not boot.
  • Some USB-serial chips need a driver on Windows and macOS, and boards without auto-reset need BOOT held manually.

FAQ

Short answers for the things developers usually ask before trusting a tool.

Are my firmware files uploaded?

No. Files are read in your browser and sent only to the board over the USB serial connection.

Can this brick my ESP32?

Practically no. The first-stage bootloader is in ROM and can't be overwritten, so a failed or interrupted flash can always be redone: hold BOOT, tap RESET, and flash again. What you can lose is data — "Erase entire flash" also wipes saved Wi-Fi credentials, NVS and filesystems. (Burning eFuses, which this tool never does, is the only truly irreversible operation.)

Which offsets should I use?

For a merged binary (one .bin file, e.g. from esptool merge_bin or the Arduino "Export compiled binary" merged output) use 0x0. For separate files: the bootloader goes at 0x1000 on ESP32 and ESP32-S2, and at 0x0 on ESP32-S3, C3, C6 and H2; the partition table at 0x8000; Arduino's boot_app0.bin at 0xE000; and the application at 0x10000. The presets fill these in for the connected chip, and flashing is blocked if a bootloader is at the wrong address.

It says "Failed to connect". What now?

Put the board in download mode by hand: hold the BOOT (IO0) button, press and release EN/RESET, then release BOOT, and connect again. Also check the cable (many are charge-only), that no serial monitor has the port open, and on Windows that the CP210x or CH340 driver is installed. If flashing fails partway, try a lower baud rate.

Which browsers work?

Desktop Chrome and Edge 89+ and other Chromium-based browsers, because flashing needs Web Serial. Firefox, Safari and mobile browsers can't flash, but can still use the tool to check file offsets.

What does "built for ESP32, but the connected chip is ESP32-C3" mean?

ESP firmware images record which chip they were compiled for. Flashing an ESP32 image to a C3 (or vice versa) will not boot, so the tool blocks it. Rebuild for the right target (in Arduino, select the matching board; in ESP-IDF, idf.py set-target).

Related tools

Useful follow-ups when one conversion usually turns into three more.