Complete API documentation for the ESP32Tool JavaScript/TypeScript library (v1.6.3).
The library can be used as an ES module in the browser (via WebSerial/WebUSB) or in Node.js (via the serialport package).
- Getting Started
- Connection Functions
- ESPLoader Class
- EspStubLoader Class
- Partition Table
- Filesystem Detection
- SPIFFS Module
- Utility Functions
- Constants
- Type Definitions
<script type="module">
import { connect, ESPLoader } from "./js/modules/esptool.js";
const logger = {
log: (msg) => console.log(msg),
error: (msg) => console.error(msg),
debug: (msg) => console.debug(msg),
};
const esploader = await connect(logger);
await esploader.initialize();
</script>import { ESPLoader, Logger } from "esp32tool";Opens a serial port selection dialog (Web Serial API) and creates an ESPLoader instance.
- Supports
WebUSBon Android via a customrequestSerialPortglobal function. - Automatically opens the port at 115200 baud (ROM default).
- Throws an error if Web Serial API is not available.
const esploader = await connect(logger);Creates an ESPLoader instance from an already-obtained SerialPort. Useful for WebUSB wrappers or when managing ports manually.
const port = await navigator.serial.requestPort();
const esploader = await connectWithPort(port, logger);The main class for communicating with ESP devices. Extends EventTarget for event-driven communication.
class ESPLoader extends EventTarget| Property | Type | Description |
|---|---|---|
port |
SerialPort |
The underlying serial port |
logger |
Logger |
Logger instance for output |
chipFamily |
ChipFamily |
Detected chip family (e.g., CHIP_FAMILY_ESP32S3) |
chipName |
string | null |
Human-readable chip name (e.g., "ESP32-S3") |
chipRevision |
number | null |
Chip silicon revision |
chipVariant |
string | null |
Chip variant string |
flashSize |
string | null |
Detected flash size (e.g., "4MB") |
connected |
boolean |
Connection state |
IS_STUB |
boolean |
Whether the stub loader is running |
currentBaudRate |
number |
Current serial baudrate |
isUsbJtagOrOtg |
boolean | undefined |
Whether USB-JTAG or USB-OTG is used (not external serial chip) |
Connects to the ESP device, detects the chip type, reads efuses, and prepares the device for further operations. Must be called after creating an ESPLoader instance.
const esploader = await connect(logger);
await esploader.initialize();
console.log(`Connected to ${esploader.chipName}`);What it does:
- Detects USB-Serial chip type (CP2102, CH340, FTDI, etc.)
- Connects using multiple reset strategies (classic, USB-JTAG)
- Detects chip family and revision
- Detects USB connection type (JTAG/OTG vs. external serial)
- Reads efuse data (MAC address, etc.)
Detects the chip type using GET_SECURITY_INFO (for ESP32-C3 and later) or magic register values (for older chips like ESP32, ESP8266).
Returns the chip family constant.
Returns security information for the connected chip (ESP32-C3 and later).
const info = await esploader.getSecurityInfo();
// { flags, flashCryptCnt, keyPurposes, chipId, apiVersion }Returns the MAC address as a formatted string (e.g., "AA:BB:CC:DD:EE:FF"). Requires initialize() to have completed successfully.
const mac = await esploader.getMacAddress();
console.log(`MAC: ${mac}`); // "AA:BB:CC:DD:EE:FF"Returns the raw MAC address as a 6-byte array from efuse data.
Reads the SPI flash manufacturer and device ID using the JEDEC RDID command.
Auto-detects the flash size and stores it in esploader.flashSize. Logs the flash manufacturer and device information.
await esploader.detectFlashSize();
console.log(`Flash: ${esploader.flashSize}`); // e.g., "4MB"Returns the bootloader flash offset for the current chip family.
Uploads and starts the stub loader on the device. The stub loader provides faster flash operations and additional capabilities.
Returns an EspStubLoader instance (a subclass of ESPLoader) that should be used for all subsequent operations.
const stub = await esploader.runStub();
// Use 'stub' for flash operations from now onParameters:
skipFlashDetection(optional, default:false) – Skip automatic flash size detection after stub upload.
Writes a binary file to flash memory at a given offset.
const firmware = await fetch("firmware.bin").then((r) => r.arrayBuffer());
await stub.flashData(
firmware,
(written, total) => console.log(`${written}/${total}`),
0x10000, // offset
true, // use compression
);Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
binaryData |
ArrayBuffer |
— | Binary data to flash |
updateProgress |
(bytesWritten: number, totalBytes: number) => void |
— | Progress callback |
offset |
number |
0 |
Flash address offset |
compress |
boolean |
false |
Use zlib compression (faster) |
Prepares for flashing by attaching the SPI chip and erasing the required number of blocks. Returns the number of blocks.
Sends one block of uncompressed data to flash memory.
Prepares for compressed flash writing. Returns the erase timeout.
Sends one block of compressed data to flash memory.
Completes an uncompressed flash write operation.
Completes a compressed flash write operation.
Reads flash memory from the chip. Requires stub loader (runStub() must be called first).
const data = await stub.readFlash(
0x0, // start address
0x400000, // size (4MB)
(packet, progress, total) => {
console.log(`${progress}/${total} bytes`);
},
);Parameters:
| Parameter | Type | Description |
|---|---|---|
addr |
number |
Flash address to read from |
size |
number |
Number of bytes to read |
onPacketReceived |
(packet: Uint8Array, progress: number, totalSize: number) => void |
Optional progress callback |
options.chunkSize |
number |
Bytes per read command (default: auto) |
options.blockSize |
number |
Bytes per data block from ESP (default: auto) |
options.maxInFlight |
number |
Max unacknowledged bytes (default: auto) |
Notes:
- Automatically adapts speed for WebUSB (Android) vs. Web Serial (Desktop)
- Includes automatic retry with recovery on read errors (up to 5 retries per chunk)
Starts downloading an application image to RAM.
Sends a block of data to RAM.
Finishes RAM download and optionally starts execution at the given entry point.
Reads a 32-bit value from a hardware register.
const value = await esploader.readRegister(0x3ff5a000);Writes a 32-bit value to a hardware register.
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
address |
number |
— | Register address |
value |
number |
— | Value to write |
mask |
number |
0xFFFFFFFF |
Write mask |
delayUs |
number |
0 |
Delay before write (µs) |
delayAfterUs |
number |
0 |
Delay after write (µs) |
Sends a raw command packet and validates the response. Returns [value, data].
Changes the serial communication baudrate on both the ESP device and the host port. Warns if the baudrate exceeds the USB-Serial chip's capability.
await stub.setBaudrate(921600);Supported baud rates: 115200, 230400, 460800, 921600, 2000000
Performs a hardware reset.
bootloader = true— Reset into bootloader/flash modebootloader = false(default) — Reset to run firmware
Automatically selects the appropriate reset strategy (classic, USB-JTAG, WDT reset) based on the chip and connection type.
Resets the device to run firmware. Returns true if the port will change (USB-OTG/JTAG devices), meaning the user must reselect the port.
const portChanged = await esploader.resetToFirmware();
if (portChanged) {
console.log("Please select the new port");
}Exits console mode and returns to the bootloader. Returns true if manual port reconnection is needed (USB-OTG devices like ESP32-S2).
Returns whether console reset is supported for this device. ESP32-S2 via USB-JTAG/CDC does not support reset in console mode (hardware limitation).
Closes the serial port connection and releases all resources. Waits for pending writes to complete.
await esploader.disconnect();ESPLoader extends EventTarget and emits custom events for loose coupling with UI code.
| Event | Detail | Description |
|---|---|---|
usb-otg-port-change |
{ chipName, message, reason } |
USB-OTG port changed (need to reselect port) |
esploader.addEventListener("usb-otg-port-change", (e) => {
console.log(e.detail.message);
});Extends ESPLoader. Created by calling runStub(). Provides additional flash operations.
class EspStubLoader extends ESPLoaderErases the entire flash chip. Warning: This erases all data!
await stub.eraseFlash();Erases a specific region of flash. Both offset and size must be aligned to the flash sector size (4096 bytes / 0x1000).
await stub.eraseRegion(0x9000, 0x6000);Parses binary partition table data into an array of Partition objects.
import { parsePartitionTable } from "esp32tool";
const partData = await stub.readFlash(0x8000, 0xC00);
const partitions = parsePartitionTable(partData);
partitions.forEach((p) => {
console.log(`${p.name}: ${p.typeName}/${p.subtypeName} @ 0x${p.offset.toString(16)}, size: ${formatSize(p.size)}`);
});Formats a byte count into a human-readable string (e.g., "4.00 MB", "256.00 KB").
interface Partition {
name: string; // Partition name (e.g., "factory", "nvs", "spiffs")
type: number; // Partition type (0x00 = app, 0x01 = data)
subtype: number; // Partition subtype
offset: number; // Start offset in flash
size: number; // Size in bytes
flags: number; // Partition flags
typeName: string; // Human-readable type (e.g., "app", "data")
subtypeName: string; // Human-readable subtype (e.g., "factory", "spiffs")
}enum FilesystemType {
UNKNOWN = "unknown",
LITTLEFS = "littlefs",
FATFS = "fatfs",
SPIFFS = "spiffs",
}Detects the filesystem type from binary image data by checking for magic signatures (LittleFS superblock, FAT boot sector, SPIFFS patterns).
const fsData = await stub.readFlash(partition.offset, partition.size);
const fsType = detectFilesystemFromImage(fsData, esploader.chipName);
console.log(`Filesystem: ${fsType}`); // "littlefs", "fatfs", "spiffs", or "unknown"Detects filesystem type from partition subtype. Only provides a hint — use detectFilesystemFromImage() for accurate detection.
Returns the default block size for a filesystem type. ESP8266 uses different block sizes (8192) than ESP32 (4096).
Returns an array of block size candidates to try for a given filesystem and chip.
Scans ESP8266 flash data for LittleFS/SPIFFS filesystem signatures and returns the detected layout.
Returns common ESP8266 filesystem layouts as fallback when flash scanning is not possible.
interface ESP8266FilesystemLayout {
start: number; // Start address in flash
end: number; // End address in flash
size: number; // Filesystem size in bytes
page: number; // Page size (typically 256)
block: number; // Block size (typically 8192)
}Main SPIFFS filesystem class for reading and writing SPIFFS images.
Reader class for extracting files from SPIFFS filesystem images.
Configuration class for building SPIFFS filesystem images.
Default ESP32 SPIFFS configuration:
const DEFAULT_SPIFFS_CONFIG = {
pageSize: 256,
blockSize: 4096,
objNameLen: 32,
metaLen: 4,
useMagic: true,
useMagicLen: true,
alignedObjIxTables: false,
};interface SpiffsFile {
// File entry from a SPIFFS filesystem
}
interface SpiffsBuildConfigOptions {
// Options for building SPIFFS images
}Converts a number to a hex string with 0x prefix, padded to the given size.
toHex(255); // "0xFF"
toHex(4096, 4); // "0x1000"
toHex(-1); // "-0x01"Asynchronous delay function.
await sleep(1000); // Wait 1 secondFormats a byte array as a hex string for debugging.
hexFormatter([0xDE, 0xAD]); // "[0xDE, 0xAD]"Formats a MAC address byte array as a colon-separated hex string.
formatMacAddr([0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF]);
// "AA:BB:CC:DD:EE:FF"| Constant | Description |
|---|---|
CHIP_FAMILY_ESP8266 |
ESP8266 |
CHIP_FAMILY_ESP32 |
ESP32 |
CHIP_FAMILY_ESP32S2 |
ESP32-S2 |
CHIP_FAMILY_ESP32S3 |
ESP32-S3 |
CHIP_FAMILY_ESP32S31 |
ESP32-S3 (variant) |
CHIP_FAMILY_ESP32C2 |
ESP32-C2 |
CHIP_FAMILY_ESP32C3 |
ESP32-C3 |
CHIP_FAMILY_ESP32C5 |
ESP32-C5 |
CHIP_FAMILY_ESP32C6 |
ESP32-C6 |
CHIP_FAMILY_ESP32C61 |
ESP32-C61 |
CHIP_FAMILY_ESP32H2 |
ESP32-H2 |
CHIP_FAMILY_ESP32H4 |
ESP32-H4 |
CHIP_FAMILY_ESP32H21 |
ESP32-H21 |
CHIP_FAMILY_ESP32P4 |
ESP32-P4 |
| Constant | Description |
|---|---|
ESP_FLASH_BEGIN |
Begin flash write |
ESP_FLASH_DATA |
Flash data block |
ESP_FLASH_END |
End flash write |
ESP_FLASH_DEFL_BEGIN |
Begin compressed flash write |
ESP_FLASH_DEFL_DATA |
Compressed flash data block |
ESP_FLASH_DEFL_END |
End compressed flash write |
ESP_MEM_BEGIN |
Begin memory write |
ESP_MEM_DATA |
Memory data block |
ESP_MEM_END |
End memory write / start execution |
ESP_SYNC |
Sync command |
ESP_WRITE_REG |
Write register |
ESP_READ_REG |
Read register |
ESP_READ_FLASH |
Read flash |
ESP_ERASE_FLASH |
Erase entire flash |
ESP_ERASE_REGION |
Erase flash region |
ESP_SPI_SET_PARAMS |
Set SPI parameters |
ESP_SPI_ATTACH |
Attach SPI flash |
ESP_CHANGE_BAUDRATE |
Change baudrate |
ESP_SPI_FLASH_MD5 |
Flash MD5 checksum |
ESP_GET_SECURITY_INFO |
Get security info |
ESP_CHECKSUM_MAGIC |
Checksum magic value |
| Constant | Value | Description |
|---|---|---|
USB_RAM_BLOCK |
— | RAM block size for USB transfers |
ESP_RAM_BLOCK |
— | RAM block size for ESP operations |
| Constant | Description |
|---|---|
DEFAULT_TIMEOUT |
Default command timeout |
CHIP_ERASE_TIMEOUT |
Timeout for full chip erase |
MAX_TIMEOUT |
Maximum allowed timeout |
SYNC_TIMEOUT |
Timeout for sync command |
ERASE_REGION_TIMEOUT_PER_MB |
Per-MB timeout for region erase |
MEM_END_ROM_TIMEOUT |
Timeout for memory end command (ROM) |
FLASH_READ_TIMEOUT |
Timeout for flash read operations |
| Constant | Value | Description |
|---|---|---|
LITTLEFS_DEFAULT_BLOCK_SIZE |
4096 |
Default LittleFS block size (ESP32) |
LITTLEFS_BLOCK_SIZE_CANDIDATES |
[4096, 2048, 1024, 512] |
LittleFS block size candidates |
FATFS_DEFAULT_BLOCK_SIZE |
4096 |
Default FATFS block size |
FATFS_BLOCK_SIZE_CANDIDATES |
[4096, 2048, 1024, 512] |
FATFS block size candidates |
ESP8266_LITTLEFS_BLOCK_SIZE |
8192 |
ESP8266 LittleFS block size |
ESP8266_LITTLEFS_BLOCK_SIZE_CANDIDATES |
[8192, 4096] |
ESP8266 block size candidates |
ESP8266_LITTLEFS_PAGE_SIZE |
256 |
ESP8266 LittleFS page size |
ESP8266_SPIFFS_PAGE_SIZE |
256 |
ESP8266 SPIFFS page size |
ESP8266_SPIFFS_BLOCK_SIZE |
8192 |
ESP8266 SPIFFS block size |
interface Logger {
log(msg: string, ...args: any[]): void;
error(msg: string, ...args: any[]): void;
debug(msg: string, ...args: any[]): void;
}import {
connect,
parsePartitionTable,
detectFilesystemFromImage,
formatSize,
formatMacAddr,
} from "esp32tool";
const logger = {
log: (msg) => console.log(`[ESP] ${msg}`),
error: (msg) => console.error(`[ESP] ${msg}`),
debug: () => {},
};
// 1. Connect and initialize
const esploader = await connect(logger);
await esploader.initialize();
console.log(`Chip: ${esploader.chipName}, Rev: ${esploader.chipRevision}`);
// 2. Get MAC address
const mac = await esploader.getMacAddress();
console.log(`MAC: ${mac}`);
// 3. Load stub for flash operations
const stub = await esploader.runStub();
console.log(`Flash: ${stub.flashSize}`);
// 4. Change baudrate for faster operations
await stub.setBaudrate(921600);
// 5. Read partition table
const partData = await stub.readFlash(0x8000, 0xC00);
const partitions = parsePartitionTable(partData);
for (const p of partitions) {
console.log(` ${p.name}: ${p.typeName}/${p.subtypeName}, offset=0x${p.offset.toString(16)}, size=${formatSize(p.size)}`);
}
// 6. Backup flash
const backup = await stub.readFlash(0x0, 0x400000, (pkt, progress, total) => {
console.log(`Reading: ${((progress / total) * 100).toFixed(1)}%`);
});
// 7. Write firmware
const firmware = await fetch("firmware.bin").then((r) => r.arrayBuffer());
await stub.flashData(firmware, (written, total) => {
console.log(`Writing: ${((written / total) * 100).toFixed(1)}%`);
}, 0x10000, true);
// 8. Reset to firmware
await stub.hardReset();
// 9. Disconnect
await esploader.disconnect();