Why HTTP on ESP32?
HTTP is the language of the web. With ESP32’s built-in Wi-Fi and the HTTPClient library, your microcontroller can talk directly to REST APIs, IoT platforms, home automation hubs, and your own backend servers. This guide covers everything from a simple GET request to authenticated HTTPS POST with JSON.
Prerequisites
- ESP32 connected to Wi-Fi (Wi-Fi Basics guide)
HTTPClient.h— built into arduino-esp32, no install needed- Optional: ArduinoJson library for parsing responses
Simple HTTP GET Request
#include <WiFi.h>
#include <HTTPClient.h>
const char* ssid = "YourSSID";
const char* password = "YourPassword";
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println("\nConnected: " + WiFi.localIP().toString());
}
void loop() {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
http.begin("http://api.open-meteo.com/v1/forecast?latitude=51.5&longitude=-0.1¤t_weather=true");
http.setTimeout(10000);
int httpCode = http.GET();
if (httpCode > 0) {
Serial.printf("HTTP %d\n", httpCode);
if (httpCode == HTTP_CODE_OK) {
String payload = http.getString();
Serial.println(payload.substring(0, 200)); // first 200 chars
}
} else {
Serial.printf("GET failed: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
}
delay(30000);
}
Parsing a JSON Response with ArduinoJson
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
// ... WiFi setup ...
void fetchWeather() {
HTTPClient http;
http.begin("http://api.open-meteo.com/v1/forecast"
"?latitude=51.5&longitude=-0.1¤t_weather=true");
if (http.GET() == HTTP_CODE_OK) {
String body = http.getString();
JsonDocument doc;
DeserializationError err = deserializeJson(doc, body);
if (!err) {
float temp = doc["current_weather"]["temperature"];
int windspeed = doc["current_weather"]["windspeed"];
Serial.printf("Temp: %.1f°C Wind: %d km/h\n", temp, windspeed);
} else {
Serial.println("JSON parse error: " + String(err.c_str()));
}
}
http.end();
}
HTTP POST — JSON Body
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
void postSensorData(float temperature, float humidity) {
HTTPClient http;
http.begin("https://your-api.example.com/sensors");
http.addHeader("Content-Type", "application/json");
http.addHeader("Authorization", "Bearer YOUR_API_TOKEN");
JsonDocument doc;
doc["device_id"] = "esp32-living-room";
doc["temperature"] = temperature;
doc["humidity"] = humidity;
doc["timestamp"] = millis();
String body;
serializeJson(doc, body);
int httpCode = http.POST(body);
Serial.printf("POST status: %d\n", httpCode);
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_CREATED) {
Serial.println("Data sent: " + http.getString());
}
http.end();
}
HTTP POST — Form-Encoded Data
HTTPClient http;
http.begin("http://192.168.1.100/api/control");
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
String payload = "relay=on&duration=5000&device=esp32";
int code = http.POST(payload);
Serial.printf("Response: %d — %s\n", code, http.getString().c_str());
http.end();
HTTPS with Certificate Validation
For production code, always validate the server’s TLS certificate. You need the root CA certificate of the server (download it from your browser’s certificate inspector or use openssl s_client -connect host:443 -showcerts).
#include <WiFi.h>
#include <HTTPClient.h>
#include <WiFiClientSecure.h>
// Root CA for your server (get from browser or openssl)
const char* root_ca = R"(
-----BEGIN CERTIFICATE-----
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
...
-----END CERTIFICATE-----
)";
void setup() {
// ... WiFi connect ...
WiFiClientSecure client;
client.setCACert(root_ca); // validates server cert
// client.setInsecure(); // TESTING ONLY — skip validation
HTTPClient https;
https.begin(client, "https://api.example.com/data");
int code = https.GET();
Serial.printf("HTTPS %d: %s\n", code, https.getString().c_str());
https.end();
}
Syncing Time for HTTPS
TLS handshakes require the ESP32 clock to be within a few minutes of real time. Sync via NTP before any HTTPS call:
#include <time.h>
void syncTime() {
configTime(0, 0, "pool.ntp.org", "time.nist.gov");
Serial.print("Syncing NTP");
time_t now = time(nullptr);
while (now < 8 * 3600 * 2) {
delay(500);
Serial.print(".");
now = time(nullptr);
}
Serial.println(" done");
}
Error Handling Reference
| Code | Constant | Meaning |
|---|---|---|
| -1 | HTTPC_ERROR_CONNECTION_REFUSED |
Server port closed or firewall blocked |
| -4 | HTTPC_ERROR_CONNECTION_LOST |
TCP connection dropped mid-transfer |
| -11 | HTTPC_ERROR_READ_TIMEOUT |
Server did not respond within timeout |
| 401 | HTTP_CODE_UNAUTHORIZED | Missing or wrong Authorization header |
| 429 | Too Many Requests | Rate limit — add exponential backoff |