ESP8266 and ESP32 serial bootloader utility
Python C Other

A Python-based, open source, platform independent, utility to communicate with the ROM bootloader in Espressif ESP8266 & ESP32 chips. was started by Fredrik Ahlberg (@themadinventor) as an unofficial community project. It is now also supported by Espressif. Current primary maintainer is Angus Gratton (@projectgus). is Free Software under a GPLv2 license.

Build Status

Installation / dependencies

Easy Installation

You will need either Python 2.7 or Python 3.4 or newer installed on your system.

The latest stable release can be installed from pypi via pip:

$ pip install esptool

(Note: stable esptool release is currently v1.x series, which does not support ESP32. See next section for manual installation.)

With some Python installations this may not work and you'll receive an error, try python -m pip install esptool or pip2 install esptool.

After installing, you will have installed into the default Python executables directory and you should be able to run it with the command

Manual Installation

Manual installation allows you to run the latest development version from this repository. depends on pySerial version 2.5 or newer for serial communication with the target device.

If you choose to install system-wide by running python install, then this will be taken care of automatically.

If not using, then you'll have to install pySerial manually by running something like pip install pyserial, easy_install pyserial or apt-get install python-serial, depending on your platform. (The official pySerial installation instructions are here). also bundles the pyaes & ecdsa Python modules as "vendored" libraries. These modules are required when using the ESP32-only and tools. If you install via pip or as shown above, then versions of these libraries will be installed from pypi. If you run from the repository directory directly, it will use the "vendored" versions.


Use -h to see a summary of all available commands and command line options.

To see all options for a particular command, append -h to the command name. ie write_flash -h.

Common Options

Serial Port

The serial port is selected using the -p option, like -p /dev/ttyUSB0 (on unixen like Linux and OSX) or -p COM1 (on Windows).

If using Cygwin on Windows, you have to convert the Windows-style name into an Unix-style path (COM1 -> /dev/ttyS0, and so on). (This is not necessary if using esp-idf for ESP32 with the supplied Windows environment, this envrionment uses a mingw Python & pyserial which accept COM ports as-is.)

Baud rate

The default baud rate is 115200bps. Different rates may be set using -b 921600 (or another baudrate of your choice). A default baud rate can also be specified using the ESPTOOL_BAUD environment variable. This can speed up write_flash and read_flash operations.

The baud rate is limited to 115200 when establishes the initial connection, higher speeds are only used for data transfers.

Most hardware configurations will work with -b 230400, some with -b 460800, -b 921600 and/or -b 1500000 or higher.

If you have connectivity problems then you can also set baud rates below 115200. You can also choose 74880, which is the usual baud rate used by the ESP8266 to output boot log information.


Convert ELF to Binary

The elf2image command converts an ELF file (from compiler/linker output) into the binary blobs to be flashed: elf2image --chip esp8266 my_app.elf

This command does not require a serial connection.

elf2image for ESP8266

The default command output is two binary files: my_app.elf-0x00000.bin and my_app.elf-0x40000.bin. You can alter the firmware file name prefix using the --output/-o option.

elf2image can also produce a "version 2" image file suitable for use with a software bootloader stub such as rboot or the Espressif bootloader program. You can't flash a "version 2" image without also flashing a suitable bootloader. --chip esp8266 elf2image --version=2 -o my_app-ota.bin my_app.elf

elf2image for ESP32

For esp32, elf2image produces a single output file. By default this has the same name as the .elf file, with a .bin extension. ie: elf2image --chip esp32 elf2image my_esp32_app.elf

In the above example, the output image would be called my_esp32_app.bin.

Writing binaries to flash

The binaries from elf2image or make_image can be sent to the chip via the serial write_flash command: --port COM4 write_flash 0x1000 my_app-0x01000.bin

For ESP8266 "Version 1" images, multiple flash addresses and file names can be given on the same command line: --port COM4 write_flash 0x00000 my_app.elf-0x00000.bin 0x40000 my_app.elf-0x40000.bin

The --chip argument is optional when writing to flash, esptool will detect the type of chip when it connects to the serial port.

The --port argument specifies the serial port. This may take the form of something like COMx (Windows), /dev/ttyUSBx (Linux) or /dev/tty.usbserial (OS X) or similar names.

The next arguments to write_flash are one or more pairs of offset (address) and file name. When generating ESP8266 "version 1" images, the file names created by elf2image include the flash offsets as part of the file name. For "version 2" images, the bootloader and linker script you are using determines the flash offset.

You may need to specify arguments for flash mode and flash size as well (flash size is autodetected in the recent versions and usually can be omitted). For example: --port /dev/ttyUSB0 write_flash --flash_mode qio --flash_size 32m 0x0 bootloader.bin 0x1000 my_app.bin

The Flash Modes section below explains the meaning of these additional arguments.

By default, uploads are compressed. The -u/--no-compress option disables this behaviour.

See the Troubleshooting section if the write_flash command is failing, or the flashed module fails to boot.

Verifying flash

You can verify an image in the flash by passing the --verify option to the write_flash command, or by using the standalone verify_flash command:

./ verify_flash 0x40000 my_app.elf-0x40000.bin

In, a separate verification step is not usually necessary. At the end of the write_flash process, the flasher reads back all data from flash and calculates an md5 hash which is compared with the original data. Explicit verification is only necessary if you think flash has been corrupted or accidentally overwritten.

NOTE: may update the first 16 bytes of the default boot image (at offset 0 for ESP8266 or offset 0x1000 for ESP32) when writing it (see Flash modes). This is to set the provided flash mode and flash size parameters for the ROM bootloader. If running verify_flash for a boot image of this type, pass matching versions of any --flash_mode or --flash_size arguments that were used for write_flash.

Manually assembling a firmware image

You can also manually assemble a firmware image from binary segments (such as those extracted from objcopy), like this: --chip esp8266 make_image -f app.text.bin -a 0x40100000 -f -a 0x3ffe8000 -f app.rodata.bin -a 0x3ffe8c00 app.flash.bin

This command does not require a serial connection.

Dumping Memory

The dump_mem command will dump a region from the chip's memory space. For example, to dump the ROM (64 KiB) from an ESP8266: dump_mem 0x40000000 65536 iram0.bin

Read built-in MAC address read_mac

ESP32-Only Commands

The following commands for ESP32, bundled with, are documented on the wiki:

Read SPI flash id flash_id

Refer to flashrom source code for flash chip manufacturer name and part number.

Read internal chip id: chip_id

On ESP8266, this is the same as the output of the system_get_chip_id() SDK function. The chip ID is four bytes long, the lower three bytes are the final bytes of the MAC address. The upper byte is zero on most (all?) ESP8266s.

On ESP32, this ID is derived from the MAC address stored in on-chip efuse.

Serial Connections

The ESP8266 & ESP32 ROM serial bootloader uses a 3.3V UART serial connection. Many development boards make the serial connections for you onboard.

However, if you are wiring the chip yourself to a USB/Serial adapter or similar then the following connections must be made:

ESP32/ESP8266 Pin Serial Port Pin
TX (aka GPIO1) RX (receive)
RX (aka GPIO3) TX (transmit)
Ground Ground

Note that TX (transmit) on the ESP8266 is connected to RX (receive) on the serial port connection, and vice versa.

Do not connect the chip to 5V TTL serial adapters, and especially not to high voltage RS-232 adapters! 3.3v serial only!

Entering the Bootloader

Both ESP8266 and ESP32 have to be reset in a certain way in order to launch the serial bootloader.

On some development boards (including NodeMCU, WeMOS, HUZZAH Feather, Core Board, ESP32-WROVER-KIT), can automatically trigger a reset into the serial bootloader - in which case you don't need to read this section.

For everyone else, three things must happen to enter the serial bootloader - a reset, required pins set correctly, and GPIO0 pulled low:

Boot Mode

Both ESP8266 and ESP32 chooses the boot mode each time it resets. A reset event can happen in one of several ways:

  • Power applied to chip.
  • The nRESET pin was low and is pulled high (on ESP8266 only).
  • The CH_PD/EN pin ("enable") pin was low and is pulled high.

On ESP8266, both the nRESET and CH_PD pins must be pulled high for the chip to start operating.

For more details on selecting the boot mode, see the following Wiki pages:

Flash Modes

write_flash and some other comands accept command line arguments to set flash mode, flash size and flash clock frequency. The chip needs correct mode, frequency and size settings in order to run correctly - although there is some flexibility.

These arguments must appear after write_flash on the command line, for example: --port /dev/ttyUSB1 write_flash --flash_mode dio --flash_size 4MB 0x0 bootloader.bin

When flashing a bootable image to an ESP8266 at offset 0x0, the image header bytes are updated automatically using these arguments. The same happens when flashing a bootable image to an ESP32 at offset 0x1000.

Flash Mode (--flash_mode, -fm)

These set Quad Flash I/O or Dual Flash I/O modes. Valid values are qio, qout, dio, dout. The default is qio. This parameter can also be specified using the environment variable ESPTOOL_FM.

Most boards use the default qio. Some ESP8266 modules, including the ESP-12E modules on some (not all) NodeMCU boards, are dual I/O and the firmware will only boot when flashed with --flash_mode dio. Most ESP32 modules are also dual I/O.

In qio mode, two additional GPIOs (9 and 10) are used for SPI flash communications. If flash mode is set to dio then these pins are available for other purposes.

Flash Size (--flash_size, -fs)

Size of the SPI flash, given in megabytes. Valid values vary by chip type:

Chip Flash Sizes
ESP8266 256KB, 512KB, 1MB, 2MB, 4MB, 2MB-c1, 4MB-c1, 4MB-c2
ESP32 1MB, 2MB, 4MB, 8MB, 16MB

The default --flash_size parameter is detect, which tries to autodetect size based on SPI flash ID. If detection fails, a warning is printed and a default value of of 4MB (4 megabytes) is used.

If flash size is not successfully detected, you can find the flash size by using the flash_id command and then looking up the ID from the output (see Read SPI flash id). Alternatively, read off the silkscreen labelling of the flash chip and search for its datasheet.

The default flash_size parameter can also be overriden using the environment variable ESPTOOL_FS.

ESP8266 and Flash Size

The ESP8266 SDK stores WiFi configuration at the "end" of flash, and it finds the end using this size. However there is no downside to specifying a smaller flash size than you really have, as long as you don't need to write an image larger than the configured size.

ESP-12, ESP-12E and ESP-12F modules (and boards that use them such as NodeMCU, HUZZAH, etc.) usually have at least 4 megabyte / 4MB (sometimes labelled 32 megabit) flash.

ESP32 and Flash Size

The ESP32 esp-idf flashes a partition table to the flash at offset 0x8000. All of the partitions in this table must fit inside the configured flash size, otherwise the ESP32 will not work correctly.

Flash Frequency (--flash_freq, -ff)

Clock frequency for SPI flash interactions. Valid values are 40m, 26m, 20m, 80m (MHz). The default is 40m (40MHz). This parameter can also be specified using the environment variable ESPTOOL_FF.

The flash chip connected to most chips works with 40MHz clock speeds, but you can try lower values if the device won't boot.

Advanced Options

The following advanced configuration options can be used for all commands (they are placed before the command name on the command line).

Reset Modes

By default, tries to hard reset the chip into bootloader mode before it starts and hard resets the chip to run the normal program once it is complete. The --before and --after options allow this behaviour to be changed:

Reset Before Operation

The --before argument allows you to specify whether the chip needs resetting into bootloader mode before talks to it.

  • --before default_reset is the default, which uses DTR & RTS serial control lines (see Entering The Bootloader) to try and reset the chip into bootloader mode.
  • --before no_reset will skip any DTR/RTS control signals and just start sending a serial synchronisation command to the chip. This is useful if your chip doesn't have DTR/RTS, or for some serial interfaces (like Arduino board onboard serial) which behave differently when DTR/RTS are toggled.
  • --before esp32r0 is a special reset sequence that can work around an automatic reset bug when using Windows with first generation ESP32 chips.

Reset After Operation

The --after argument allows you to specify whether the chip should be reset after the operation completes:

  • --after hard_reset is the default. The DTR serial control line is used to reset the chip into a normal boot sequence.
  • --after soft_reset is currently only supported on ESP8266. This runs the user firmware, but any subsequent reset will return to the serial bootloader. This was the reset behaviour in v1.x.
  • --after no_reset leaves the chip in the serial bootloader, no reset is performed.

Disabling Boot Stub

The --no-stub option disables uploading of a software "stub loader" that manages flash operations, and only talks directly to the loader in ROM.

Passing --no-stub will disable certain options, as not all options are implemented in every chip's ROM loader.

Specifying Arguments Via File

Anywhere on the command line, you can specify a file name as @filename.txt to read one or more arguments from text file filename.txt. Arguments can be separated by newlines or spaces, quotes can be used to enclose arguments that span multiple words. Arguments read from the text file are expanded exactly as if they had appeared in that order on the command line.


Flashing problems can be fiddly to troubleshoot. Try the suggestions here if you're having problems:

Bootloader won't respond

If you see errors like "Failed to connect" then your chip is probably not entering the bootloader properly:

  • Check you are passing the correct serial port on the command line.
  • Check you have permissions to access the serial port, and other software (such as modem-manager on Linux) is not trying to interact with it. A common pitfall is leaving a serial terminal accessing this port open in another window and forgetting about it.
  • Check the chip is receiving 3.3V from a stable power source (see Insufficient Power for more details.)
  • Check that all pins are connected as described in Entering the bootloader. Check the voltages at each pin with a multimeter, "high" pins should be close to 3.3V and "low" pins should be close to 0V.
  • If you have connected other devices to GPIO pins mentioned above section, try removing them and see if starts working.
  • Try using a slower baud rate (-b 9600 is a very slow value that you can use to verify it's not a baud rate problem.)

write_flash operation fails part way through

If flashing fails with random errors part way through, retry with a lower baud rate.

Power stability problems may also cause this (see Insufficient Power.)

write_flash succeeds but program doesn't run

If can flash your module with write_flash but your program doesn't run, try the following:

Wrong Flash Mode

Some devices only support the dio flash mode. Writing to flash with qio mode will succeed but the chip can't read the flash back to run - so nothing happens on boot. Try passing the -fm dio option to write_flash.

Insufficient Power

The 3.3V power supply for the ESP8266 and ESP32 has to supply large amounts of current (up to 70mA continuous, 200-300mA peak, slightly higher for ESP32). You also need sufficient capacitance on the power circuit to meet large spikes of power demand.

If you're using a premade development board or module then the built-in power regulator is usually good enough, provided the input power supply is adequate.

It is possible to have a power supply that supplies enough current for the serial bootloader stage with, but not enough for normal firmware operation. You may see the 3.3V VCC voltage droop down if you measure it with a multimeter, but you can have problems even if this isn't happening.

Try swapping in a 3.3V supply with a higher current rating, add capacitors to the power line, and/or shorten any 3.3V power wires.

The 3.3V output from FTDI FT232R chips/adapters or Arduino boards do not supply sufficient current to power an ESP8266 or ESP32 (it may seem to work sometimes, but it won't work reliably). Other USB TTL/serial adapters may also be marginal.

Missing bootloader

Recent ESP8266 SDKs and the ESP32 esp-idf both use a small firmware bootloader program. The hardware bootloader in ROM loads this firmware bootloader from flash, and then it runs the program. On ESP8266. firmware bootloader image (with a filename like boot_v1.x.bin) has to be flashed at offset 0. If the firmware bootloader is missing then the ESP8266 will not boot. On ESP32, the bootloader image should be flashed by esp-idf at offset 0x1000.

Refer to SDK or esp-idf documentation for details regarding which binaries need to be flashed at which offsets.

SPI Pins which must be disconnected

Compared to the ROM bootloader that talks to, a running firmware uses more of the chip's pins to access the SPI flash.

If you set "Quad I/O" mode (-fm qio, the default) then GPIOs 7, 8, 9 & 10 are used for reading the SPI flash and must be otherwise disconnected.

If you set "Dual I/O" mode (-fm dio) then GPIOs 7 & 8 are used for reading the SPI flash and must be otherwise disconnected.

Try disconnecting anything from those pins (and/or swap to Dual I/O mode if you were previously using Quad I/O mode but want to attach things to GPIOs 9 & 10). Note that if GPIOs 9 & 10 are also connected to input pins on the SPI flash chip, they may still be unsuitable for use as general purpose I/O.

In addition to these pins, GPIOs 6 & 11 are also used to access the SPI flash (in all modes). However flashing will usually fail completely if these pins are connected incorrectly.

Early stage crash

Use a serial terminal program to view the boot log. (ESP8266 baud rate is 74880bps, ESP32 is 115200bps). See if the program is crashing during early startup or outputting an error message. See Boot log for an example.

Serial Terminal Programs

There are many serial terminal programs suitable for debugging & serial interaction. The pyserial module (which is required for includes one such command line terminal program - For more details see this page or run miniterm -h.

Note that not every serial program supports the unusual ESP8266 74880bps "boot log" baud rate. Support is especially sparse on Linux. supports this baud rate on all platforms. ESP32 uses the more common 115200bps.

Internal Technical Documentation

The repository wiki contains some technical documentation regarding the serial protocol and file format used by the ROM bootloader. This may be useful if you're developing or hacking system internals:

About was initially created by Fredrik Ahlberg (@themadinventor, @kongo), and is currently maintained by Angus Gratton (@projectgus). It has also received improvements from many members of the ESP8266 community - including @rojer, @jimparis, @jms19, @pfalcon, @tommie, @0ff, @george-hopkins and others.

This document and the attached source code are released under GNU General Public License Version 2. See the accompanying file LICENSE for a copy.