Wer mit dem ESP32 arbeitet, kennt die Situation: Ein Projekt läuft stabil, die Firmware ist getestet – und nun soll sie auf weitere Boards übertragen oder für andere verfügbar gemacht werden. Genau hier hilft ein Firmware-Backup. Es sorgt für Sicherheit, ermöglicht das Klonen auf neue Geräte und eröffnet die Möglichkeit, die Firmware sogar über einen Webinstaller im Browser bereitzustellen. In diesem Beitrag zeige ich dir Schritt für Schritt, wie du deine ESP32-Firmware sicherst, wiederherstellst und ggf. komfortabel verteilst.

Dokumentation des ESPTool vom Hersteller Espressif: esptool latest documentation
Übersicht der Schritte
- Voraussetzung der Arbeitsumgebung
- Firmware-Backup mit ESPTool
- Wiederherstellen/Klonen auf ein neues ESP32
- Bereitstellung über Webinstaller Web Serial API (Optional)
- Lokaler Test mit Mini Python-Webserver
Schritt 1: Voraussetzung der Arbeitsumgebung
Bevor du mit Backup, Klonen und Webinstaller startest, stelle sicher, dass deine Umgebung passt. Siehe am Ende der Anleitung, was die Voraussetzungen deiner Arbeitsumgebung sind und ob diese passen.
Schritt 2: Firmware-Backup mit ESPTool
Vorab ESPTool installieren im Windows 11 Terminal / Powershell (als Admin) mit:
PS C:\Users\deinUserName> pip install esptooldanach angebotenes update auf 25.2 -> 25.3 ausgeführt.
Verbinde nun deinen ESP32 mit dem PC und prüfe ggf. den COM-Port im Gerätemanager. Führe im Terminal folgenden Befehl aus:
PS C:\Users\DeinUserName> python -m esptool -p COM5 flash-id
esptool v5.1.0
Connected to ESP32 on COM5:
Chip type: ESP32-D0WDQ6 (revision v1.0)
Features: Wi-Fi, BT, Dual Core + LP Core, 240MHz, Vref calibration in eFuse, Coding Scheme None
Crystal frequency: 40MHz
MAC: 00:bb:11:ff:55:44
Stub flasher running.
Flash Memory Information:
=========================
Manufacturer: 5e
Device: 4016
Detected flash size: 4MB
Flash voltage set by a strapping pin: 3.3VWenn nichts erscheint: Achte auf richtigen COM Port – (Bei mir Com5)
Perfekt, bei mir steht die Verbindung. Die Fakten liegen auf dem Tisch: Ich habe einen klassischen ESP32-D0WDQ6 mit 4MB Flash am Start.
Da ich jetzt die exakte Speichergröße kenne (4MB entspricht hexadezimal 0x400000), werde ich nun den Klon-Vorgang starten.
Ich habe die Befehle so angepasst, dass sie auch ohne PATH-Variable (python -m ...) funktionieren.
Firmware auslesen (Backup)
Wir lesen den kompletten Speicher von Adresse 0 bis 4MB aus, inkl. Bootloader, Partition Table, App
- Lass den Source-ESP32 an COM5 angeschlossen.
- Führe diesen Befehl in der PowerShell aus:
python -m esptool -p COM5 -b 921600 read-flash 0 0x400000 esp32_backup.binErklärung der Parameter:
-b 921600: Erhöht die Lesegeschwindigkeit massiv (Standard ist 115200). Falls es Fehler gibt, nimm diesen Teil raus.0: Startadresse.0x400000: Bei Größe (4MB).esp32_backup.bin: Dateiname, die Datei landet in deinem aktuellen Verzeichnis (wo die PowerShell gerade steht).

Schritt 3: Wiederherstellen/Klonen auf ein neues ESP32 (Restore)
Jetzt wird der Klon mit dem erzeugten Backup bespielt:
- Trenne den alten ESP32 vom USB.
- Schließe den neuen, baugleichen ESP32 an (prüfe kurz, ob er auch an COM5 erkannt wird, sonst Port im Befehl anpassen).
- Führe den Schreib-Befehl aus:
python -m esptool -p COM5 -b 921600 write-flash 0 esp32_backup.binDas Tool entpackt und schreibt das Binary automatisch an den Start (Adresse 0).

Ich hoffe es klappt bei euch genauso gut.
Damit sollte das Hauptthema hoffentlich gut nachvollziehbar sein.
Optional: Schritt 4 – Automatisiere lokaler Web Installer
Wenn du schon mal mehrere ESPs mit dem gleichen Stand flashen musst oder mehrere verschiedene Projekte schnell auf Abruf flashen willst, ist diese WebInstaller Lösung bestimmt auch noch interessant für dich.
Das Stichwort hier lautet Web Serial API.
Der Industriestandard dafür sind die ESP Web Tools (entwickelt von den Machern von Home Assistant). Das ist keine Bastellösung, sondern eine robuste, auf JavaScript basierende Schnittstelle, die direkt im Browser (Chrome, Edge) auf die serielle Schnittstelle des PCs zugreift.
Was eigentlich für Web Server gedacht ist, nutze ich lokal an meinem Rechner um komfortabler ESP-Module zu flashen. Dennoch versuche ich hier mal auch die notwendigsten Infos zusammen zu stellen um das auch auf einem eigenen Web Server zu realisieren:
Voraussetzung (Fakten-Check)
- HTTPS ist Pflicht: Die Web Serial API funktioniert aus Sicherheitsgründen nur in einem sicheren Kontext (HTTPS). Da du eine professionelle Seite betreibst, setze ich das voraus.
- Browser-Kompatibilität: Das funktioniert aktuell nur in Chromium-basierten Browsern (Chrome, Edge, Opera, Brave). Firefox und Safari unterstützen die Web Serial API (noch) nicht. Darauf solltest du deine Leser hinweisen.
- Datei-Hosting: Deine
esp32_backup.binmuss auf deinem Webserver liegen.
Die Umsetzung
Wir nutzen ein Custom HTML Element, das die gesamte Logik (Verbindung, Erasing, Flashing) kapselt. <esp-web-install-button>.
Du benötigst drei Dinge auf deinem Webserver im selben Verzeichnis:
- Deine erstellete Backup Datei:
esp32_backup.bin - Eine Manifest-Datei:
manifest.json - Den HTML-Code für die aufzurufende Webseite.
4.1. Die Manifest-Datei (manifest.json)
Da du bereits ein komplettes Image (inkl. Bootloader, Partition Table, App) ab Adresse 0x0000 hast, ist die Konfiguration sehr simpel. Erstelle eine Datei namens manifest.json:
{
"name": "Prilchen ESP32 Projekt",
"version": "1.0.0",
"new_install_prompt_erase": true,
"builds": [
{
"chipFamily": "ESP32",
"parts": [
{ "path": "esp32_backup.bin", "offset": 0 }
]
}
]
}- offset 0: Wichtig, da dein Backup bei Adresse 0 beginnt.
- new_install_prompt_erase: Fragt den User, ob er den Flash vorher löschen will (empfohlen bei Komplett-Images).
4.2. Der HTML-Code für deine Webseite
Füge folgenden Code (Teilausschnitt) an der Stelle ein, wo der Button erscheinen soll. Das Skript lädt die Logik dynamisch von einem Content Delivery Network (unpkg.com).
<script type="module" src="https://unpkg.com/esp-web-tools@10/dist/web/install-button.js?module"></script>
<esp-web-install-button
manifest="manifest.json"
>
<button slot="activate">Verbinden & Installieren</button>
<span slot="unsupported">
Dein Browser unterstützt Web Serial nicht. Bitte nutze Chrome oder Edge.
</span>
<span slot="not-allowed">
Bitte nutze eine HTTPS-Verbindung.
</span>
</esp-web-install-button>Wichtige Hinweise für den Webserver-Admin
Damit das reibungslos läuft, müssen dein Webserver (Apache/Nginx) die richtigen MIME-Types und CORS-Header senden, falls die Dateien nicht exakt vom selben Origin geladen werden.
- MIME-Types: Stelle sicher, dass dein Server
.jsonalsapplication/jsonund.binalsapplication/octet-streamausliefert. - CORS (Cross-Origin Resource Sharing): Wenn
prilchen.dedas Skript lädt, aber die Firmware vielleicht auf einer Subdomain oder einem CDN liegt, brauchst du CORS-Header. Liegt alles im selben Ordner auf derselben Domain, ist das meist kein Problem.
Schritt 5: Web Installer – Lokaler Test mit Mini Python-Webserver
5.1. Die Dateistruktur
Sofern noch nicht umgesetzt, erstelle einen neuen Ordner (z. B. webinstaller_test) und lege dort folgende drei Dateien hinein:
esp32_backup.bin(Dein Backup)manifest.json(Der Code von oben)index.html(Vollständige Beispiel Seite siehe unten)

5.2. Der Code für die index.html
Hier ist eine saubere Vorlage mit etwas integrierten CSS, damit es ordentlich aussieht. Passe diesen nach deinen Vorstellungen an:
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Prilchen ESP32 Web Installer</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
background-color: #f4f4f9;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}
.container {
background: white;
padding: 2rem;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
text-align: center;
max-width: 400px;
}
h1 { margin-top: 0; color: #333; }
p { color: #666; margin-bottom: 20px; }
/* Styling für den Custom-Button Container */
esp-web-install-button {
display: block;
margin-top: 1rem;
}
button {
background-color: #007bff;
color: white;
border: none;
padding: 10px 20px;
border-radius: 5px;
font-size: 16px;
cursor: pointer;
transition: background 0.3s;
}
button:hover { background-color: #0056b3; }
</style>
<script type="module" src="https://unpkg.com/esp-web-tools@10/dist/web/install-button.js?module"></script>
</head>
<body>
<div class="container">
<h1>Prilchen Installer</h1>
<p>Schließe deinen ESP32 via USB an und klicke auf den Button, um die neueste Firmware zu installieren.</p>
<esp-web-install-button manifest="manifest.json">
<button slot="activate">Verbinden & Installieren</button>
<span slot="unsupported" style="color:red;">Dein Browser ist nicht kompatibel. Bitte nutze Chrome oder Edge.</span>
<span slot="not-allowed" style="color:red;">Nur über HTTPS oder localhost nutzbar.</span>
</esp-web-install-button>
<p style="font-size: 0.8rem; margin-top: 20px; color: #999;">
Powered by ESP Web Tools
</p>
</div>
</body>
</html>
5.3. Den lokalen Webserver starten
Öffne deine PowerShell, navigiere in den erstellten Ordner „webinstaller_test“ und führe dort folgenden Befehl aus:
python -m http.server 8000Windows fragt eventuell nach einer Firewall-Freigabe -> Zulassen.
PowerShell Terminal geöffnet lassen
5.4. Testen
- Öffne deinen Browser (Chrome oder Edge).
- Rufe die Adresse auf:
http://localhost:8000 - Du solltest jetzt deine Seite sehen.
- Schließe den neuen ESP32 an und klicke auf „Verbinden & Installieren“.

- Der Browser fragt nach dem COM-Port

- Es kommt die eingetragene Sicherheitsabfrage ob wirklich gelöscht werden soll

- ggf nun den Boot‑Button drücken, Beginnt nun mit dem Flashen.

- Fertig 🙂
Sollte im Sketch Ausgaben im Seriellen Monitor zu sehen sein oder man will nun den Neustart LOG sehen wollen, dann Auswahl Logs & Console. Hier kann auch ein Reset ausgelöst werden.

Wie stoppt man wieder den lokaler Webserver ordentlich?
Mit STRG – C (bzw. CTRL + C).

Nicht Fenster einfach schließen! Würdest du einfach das Fenster über das „X“ schließen, wird der Prozess oft hart beendet (SIGTERM/SIGKILL), und es kann passieren, dass der Port 8000 vom Betriebssystem noch für einige Sekunden oder Minuten als „belegt“ (TIME_WAIT) markiert bleibt.
Voraussetzungen der Arbeitsumgebung und Fehlersuche
Bevor du mit Backup, Klonen und Webinstaller startest, stelle sicher, dass deine Umgebung passt.
Betriebssystem, Treiber und Browser
- OS: Windows 10/11, macOS oder Linux (x64/ARM; Admin-/sudo‑Zugriff empfohlen).
- Serielle Treiber:
- Windows: CP210x/CH340/FTDI Treiber installieren (für viele ESP32‑USB‑Adapter nötig).
- macOS/Linux: Meist bereits vorhanden; bei Problemen Treiber bzw. udev‑Regeln ergänzen.
- Browser (Webinstaller): Aktuelle Chromium‑Variante (Chrome, Edge, Brave) mit Web Serial API; Seite muss über HTTPS oder
http://localhosterreichbar sein.
Python installieren
- Python: derzeit Version 3.13.9 installiert im Windows 11 Terminal / Powershell (als Admin) mit:
winget install Python.Python.3.13
Hardware und Verbindung
- Boards: ESP32 (z. B. ESP32‑D0WDQ6, 4 MB Flash) oder kompatible Klone.
- Kabel: Datenfähiges USB‑Kabel (nicht nur Ladefunktion).
- passenden COM/tty‑Port: Im Geräte‑Manager (Windows)
oderls /dev/tty.*/dmesg(macOS/Linux) finden. - Boot/Reset: Bei manchen Devboards Boot‑Button beim Reset halten, falls Flashen nicht startet.
Berechtigungen und Stolpersteine
- Windows: Terminal als Administrator starten, wenn Ports blockiert sind.
- Linux: Benutzer zur
dialout‑Gruppe hinzufügen:sudo usermod -aG dialout $USER
Danach ab- und wieder anmelden. - macOS: USB‑Zugriff im Browser erlauben, falls Sicherheitsnachfrage erscheint.
- Baudrate: Bei Übertragungsfehlern -b 921600 weglassen und mit Standard‑Baudrate testen.
- Flashgröße: Befehle und Offsets müssen zur tatsächlichen Flash‑Größe passen (häufig 4 MB = 0x400000, bei 8MB = 0x800000).
