Making ESP32 HTTPS REST API calls with SSL certificates is essential for any IoT project that exchanges sensitive data with web services. Whether you’re sending sensor readings to a server, retrieving weather data, or posting to a webhook, using HTTPS ensures your data is encrypted in transit. This tutorial covers everything Indian makers need to know about implementing secure HTTP requests on the ESP32 using the Arduino framework.
Table of Contents
- Why HTTPS Matters for IoT in India
- SSL/TLS Basics for ESP32
- Getting the SSL Certificate
- Using HTTPClient with HTTPS
- WiFiClientSecure for Custom Requests
- Common API Integrations
- Troubleshooting SSL Errors
- Frequently Asked Questions
Why HTTPS Matters for IoT in India
In 2026, nearly every public API requires HTTPS. Sending data over plain HTTP exposes it to interception — a real concern given how many Indian users operate IoT devices on shared apartment WiFi networks. Key reasons to use HTTPS:
- APIs like OpenWeatherMap, ThingSpeak, and Telegram Bot API now mandate HTTPS
- Prevents MITM attacks on shared WiFi networks common in PGs and apartments
- Required for sending sensitive data (user tokens, API keys, health data)
- Many IoT cloud platforms (AWS IoT, Azure IoT Hub) only accept TLS connections
SSL/TLS Basics for ESP32
The ESP32 supports TLS 1.1 and TLS 1.2 natively through the mbedTLS library built into the ESP-IDF. In Arduino framework, this is exposed through the WiFiClientSecure class. There are three modes of SSL verification:
1. Full Certificate Verification (Most Secure)
The ESP32 verifies the server’s SSL certificate against a trusted root CA (Certificate Authority). This prevents MITM attacks but requires storing the root CA certificate in your firmware.
2. Certificate Fingerprint Verification
Verify only the SHA-256 fingerprint of the specific server certificate. Simpler than full CA verification but breaks when the certificate renews (typically every 90 days for Let’s Encrypt certs).
3. Insecure Mode (Not Recommended)
Skip certificate verification entirely with client.setInsecure(). Encrypts data but does NOT verify server identity. Acceptable only for internal private APIs or during development.
Getting the SSL Certificate
To verify a server’s certificate on ESP32, you need the Root CA certificate in PEM format.
Method 1: Using OpenSSL (Linux/Mac)
# Get the certificate chain for a server
openssl s_client -connect api.openweathermap.org:443 -showcerts 2>/dev/null |
openssl x509 -noout -text
# Save the root CA certificate
openssl s_client -connect api.openweathermap.org:443
-servername api.openweathermap.org 2>/dev/null |
sed -n '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p' > cert.pem
Method 2: Browser Export
- Visit the HTTPS website in Chrome
- Click the padlock icon → Certificate → Details
- Select the root certificate (topmost in the chain)
- Export as Base64-encoded PEM format
- Copy the content into your Arduino sketch
Method 3: Use Known Root CAs
Major services use well-known CAs. You can find their root certificates in the certs folder of the ESP32 Arduino core or in the Mozilla Root CA bundle.
Using HTTPClient with HTTPS
The simplest approach uses the HTTPClient library which handles connection management automatically:
#include <WiFi.h>
#include <HTTPClient.h>
#include <WiFiClientSecure.h>
// Root CA certificate (ISRG Root X1 for Let's Encrypt)
const char* rootCACert =
"-----BEGIN CERTIFICATE-----n"
"MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwn"
"...(certificate data)...n"
"-----END CERTIFICATE-----n";
void setup() {
Serial.begin(115200);
WiFi.begin("YOUR_SSID", "YOUR_PASSWORD");
while (WiFi.status() != WL_CONNECTED) delay(500);
Serial.println("WiFi connected");
}
void fetchWeather() {
WiFiClientSecure secureClient;
secureClient.setCACert(rootCACert);
HTTPClient https;
String url = "https://api.openweathermap.org/data/2.5/weather"
"?q=Mumbai,IN&appid=YOUR_API_KEY&units=metric";
if (https.begin(secureClient, url)) {
int httpCode = https.GET();
if (httpCode == HTTP_CODE_OK) {
String payload = https.getString();
Serial.println(payload);
// Parse JSON with ArduinoJson
} else {
Serial.printf("HTTP error: %dn", httpCode);
}
https.end();
}
}
void loop() {
fetchWeather();
delay(60000); // Fetch every minute
}
WiFiClientSecure for Custom Requests
For more control, use WiFiClientSecure directly — useful for POST requests with JSON bodies:
#include <WiFiClientSecure.h>
#include <ArduinoJson.h>
void postSensorData(float temperature, float humidity) {
WiFiClientSecure client;
client.setCACert(rootCACert);
if (!client.connect("api.thingspeak.com", 443)) {
Serial.println("Connection failed");
return;
}
// Build JSON payload
String postData = "api_key=YOUR_WRITE_KEY";
postData += "&field1=" + String(temperature);
postData += "&field2=" + String(humidity);
// HTTP POST request
client.println("POST /update HTTP/1.1");
client.println("Host: api.thingspeak.com");
client.println("Content-Type: application/x-www-form-urlencoded");
client.print("Content-Length: ");
client.println(postData.length());
client.println();
client.println(postData);
// Read response
while (client.connected()) {
String line = client.readStringUntil('n');
if (line == "r") break; // Headers done
}
String response = client.readString();
Serial.println("ThingSpeak entry: " + response);
client.stop();
}
Common API Integrations
1. Telegram Bot API
Telegram uses Let’s Encrypt certificates. Use the ISRG Root X1 certificate or call client.setInsecure() for quick testing:
// Send Telegram message
void sendTelegram(String message) {
WiFiClientSecure client;
client.setInsecure(); // Quick dev setup
HTTPClient https;
String url = "https://api.telegram.org/bot" +
String(BOT_TOKEN) + "/sendMessage";
https.begin(client, url);
https.addHeader("Content-Type", "application/json");
String payload = "{"chat_id":"" +
String(CHAT_ID) +
"","text":"" + message + ""}";
int code = https.POST(payload);
https.end();
}
2. OpenWeatherMap API
Popular with Indian weather station projects. Free tier allows 1,000 calls/day:
String getWeather(String city) {
// city format: "Mumbai,IN" or "Bengaluru,IN"
String url = "https://api.openweathermap.org/data/2.5/weather?q="
+ city + "&appid=" + API_KEY + "&units=metric";
// ... HTTPS GET as shown above
}
3. Firebase Realtime Database
Store and retrieve sensor data in Firebase — many Indian IoT projects use Firebase for its generous free tier:
void writeToFirebase(float temp) {
WiFiClientSecure client;
client.setCACert(firebaseRootCA); // Use Firebase's CA
String url = "https://YOUR-PROJECT.firebaseio.com/sensors.json";
// ... HTTPS PUT request
}
Troubleshooting SSL Errors
Common Error: “SSL Handshake Failed”
Causes and solutions:
- Wrong certificate: Verify you have the correct root CA for the server. Use OpenSSL to check the full certificate chain.
- Time synchronisation: SSL certificates have validity periods. ESP32 needs correct time — add NTP sync in setup().
- Memory: SSL uses 30–40KB of RAM. Avoid loading large JSON alongside SSL on memory-constrained projects.
- Expired cert: If using fingerprint verification, the cert may have renewed. Switch to CA-based verification instead.
NTP Time Sync (Required for Certificate Verification)
#include <time.h>
void syncTime() {
configTime(19800, 0, "pool.ntp.org"); // IST = UTC+5:30 = 19800s
struct tm timeinfo;
while (!getLocalTime(&timeinfo)) {
delay(1000);
Serial.println("Waiting for NTP...");
}
Serial.println(&timeinfo, "Time: %A, %B %d %Y %H:%M:%S");
}
Frequently Asked Questions
How much memory does SSL use on ESP32?
A single TLS connection uses approximately 30–45KB of heap memory. The ESP32 has 320KB of RAM (plus external PSRAM on some variants), leaving plenty for application logic. Avoid maintaining multiple simultaneous TLS connections on memory-sensitive applications.
Can I use HTTPS on ESP8266?
Yes. The ESP8266 supports TLS through the BearSSL library (included in the ESP8266 Arduino core). The approach is identical — use WiFiClientSecure with setCACert(). However, ESP8266’s 80KB usable RAM limits complex SSL use cases.
How do I update the certificate when it expires?
If using root CA verification, you’re protected from individual certificate renewals — root CA certificates typically last 10–30 years. Only update your code if the root CA changes. If using fingerprint verification, you must re-flash firmware every 90 days for Let’s Encrypt certs.
Is it safe to store API keys in ESP32 firmware?
API keys embedded in firmware can be extracted from the binary with some effort. For production projects, implement a token server that issues short-lived tokens to your ESP32 on startup. For hobby projects, embed the key but rotate it if the device is ever sold or lost.
Does HTTPS work over ESP32’s soft-AP mode?
HTTPS requires internet connectivity to validate certificates (time sync) and reach external APIs. It does not work in AP-only mode without internet. For LAN-only setups, generate a self-signed certificate with a local CA and install that CA on your ESP32.
Add comment