ESP8266 NodeMCU HTTPS Requests (Arduino IDE)

In this guide, you’ll learn how to make HTTPS requests with the ESP8266 NodeMCU board. We’ll introduce you to some HTTPS fundamental concepts and provide several examples: HTTPS requests without certificate, with fingerprint and with certificate.

ESP8266 NodeMCU HTTPS requests Arduino IDE Core

We have a similar tutorial for the ESP32 board:

Table of Contents

Throughout this article, we’ll cover the following subjects:

Introduction

To understand how to make HTTPS requests with the ESP8266, it’s better to be familiar with some fundamental concepts that we’ll explain next. We also recommend taking a look at the following article:

What is HTTPS?

HTTPS is the secure version of the HTTP protocol, hence the “S”, which stands for secure.

HTTP is a protocol to transfer data over the internet. When that data is encrypted with SSL/TLS, it’s called HTTPS.

HTTP vs HTTPS protocol

To simplify, HTTPS is just the HTTP protocol but with encrypted data using SSL/TLS.

Why do you need HTTPS with the ESP8266?

Using HTTPS ensures the following:

1) Encryption: all traffic between the ESP8266 and a server will be encrypted—no one can spy on your requests and passwords, they will only see gibberish.

ESP8266 HTTPS requests encrypted

When using the ESP8266 libraries to make HTTPS requests, they take care of encryption and decryption of the messages.

2) Server trust (identification): when using HTTPS, via TLS/SSL certificates, you ensure you are connected to the server you would expect—this means, you always know to who you are connected to.

SSL/TLS Certificate valid

To make sure we are connected to the right server, we need to check the server certificate on the ESP8266 or the server fingerprint. This means we need to download the server certificate or fingerprint and hard code it on our sketch so that we can check if we’re actually connected to the server we are expecting.

TLS/SSL Certificates

SSL certificates are issued by legitimate Certificate Authorities. One of the most known is LetsEncrypt. Certificate Authorities confirm the identity of the certificate owner and provide proof that the certificate is valid. The certificate also contains the server’s public key for asymmetrically encrypted communication with a client.

TLS SSL Certificate Public Key

When a Certificate Authority issues a certificate, it signs the certificate with its root certificate. This root certificate should be on the database of trusted certificates called a root store. Your browser and the operating system contain a database of root certificates that they can trust (root store). The following screenshot shows some of the trusted root certificates.

trusted root certificates chrome

So, when you connect to a website using your browser, it checks if its certificate was signed by a root certificate that belongs to its root store. New root certificates are added or deleted to the root store with each browser update.

client server TLS SSL Certificates

When you’re using an ESP8266, you need to upload the certificates that you trust to your board. Usually, you’ll add only the certificate for the server you’ll want to connect to.

ESP8266 Check server certificate for secure connection

But, it’s also possible to upload a root store to your board to have more options, and don’t have to worry about searching for a specific website’s certificate.

Certificate Chain

An SSL certificate is part of an SSL certificate chain. What is a certificate chain?

A certificate chain includes the following:

  • root certificate (from a Certificate Authority);
  • one or more intermediate certificates;
  • the server certificate.

The server certificate is what makes your browser show a secure padlock icon when you visit a website. It means the server has a valid SSL/TLS certificate and all the connections with the website are encrypted. A valid SSL/TLS certificate is a certificate trusted by your browser. What makes it trustable?

As we’ve mentioned previously, SSL/TLS certificates are issued by Certificate Authorities. However, these authorities don’t issue certificates directly to websites. They use intermediates that will issue the server certificate (Certificate Authority > intermediate certificate > server certificate). The following screenshot shows an example for the Github website. You can see the certificate hierarchy highlighted with a red rectangle.

SSL Certificate Chain

Your browser checks this certificate chain until it finds the root certificate. If that certificate is in the browser’s root store, then it considers the certificate to be valid. In this case, the DigiCert Global Root CA is in the browser’s root store. So, it will display the “secure” icon on the browser bar.

github secure icon

The following diagram shows a high-level overview of how it works.

certificate chain example

In summary:

  • root certificate: it’s a self-signed certificate issued by a Certificate Authority. The private key of this certificate is used to sign the next certificate in the hierarchy of certificates. Root certificates are loaded in the trust stores of browsers and operating systems.
  • intermediate certificate: it’s signed by the private key of the root certificate. The public key of the intermediate certificate is the one that signs the server certificate. There can be more than one intermediate certificate.
  • server certificate: this certificate is issued to a specific domain name on a server. It’s signed by the intermediate certificate public key. If it is valid (trustable certificate chain), the browser displays a secure padlock badge on the search bar next to the website domain.

With the ESP8266, to check the validity of a server, you can load any of those certificates: root, intermediate, or server certificate. Instead of the certificate, you can also check the certificate fingerprint. The fingerprint is a hash of the certificate (a unique identifier of the certificate generated from the certificate information).

Certificates Expiration Date

SSL/TLS certificates have an expiry date. You can check on a browser the expiry date of the certificate for a particular server. The server’s certificate usually has a short-term validity and the fingerprint validity is even shorter.

So, if you want to use them in your ESP8266 projects, you’ll need to update your code quite frequently. If you want your code to run for years without worrying, you can use the website’s root certificate, which usually has a validity of five to ten years or more. However, using the fingerprint might be useful for testing purposes or might be a good option depending on the application.

Getting a Server’s Certificate

There are different ways to get the server’s certificate. One of the easiest ways is to download the certificate directly from your browser. You can also use OpenSSL and get all the certificate information you need using the command line (we won’t cover this method in this tutorial).

In this section, you’ll learn how to get the server’s certificate. We’ll generally use the root certificate, but you can use any of the other certificates on the certificate chain—you just need to be aware of the certificate expiry date.

Getting a Server’s Certificate using Google Chrome

In this section, we’ll show you how to get the certificate for a server using Google Chrome (that’s the web browser we use more often). Instructions for other web browsers should be similar.

The examples we’ll use later show how to make an HTTPS request to the howmyssl.com website. So, for demonstration purposes, we’ll show you how to get its root certificate. It is similar for other websites.

How to Get Websites’s Certificate using Google Chrome?

  1. Go to the website that you want to get the certificate for.
  1. Click on the padlock icon and then click on Show connection details.
Google chrome website certificate ssl
  1. Then, click on Show certificate.
Google chrome website certificate ssl information
  1. A new window will open with all the information about the website’s certificate. Click on the Details tab, make sure you select the root certificate (that’s what we’re looking for in this example), then click on Export…
Google chrome website certificate ssl details
  1. Select a place on your computer to save the certificate. Save it on the default format: Base64-encoded ASCII, single certificate (*.pem, .crt). And that’s it.

You can double-click on the certificate file to check its details, including the expiration date.

Google chrome website certificate ssl certificate information expanded

Open the certificate using Notepad or other similar software. You should get something similar as shown below.

SSL certificate notepad

How to Get a Website’s Fingerprint using Google Chrome?

Getting a website’s certificate fingerprint is straightforward. Follow the next instructions:

  1. Go to the website that you want to get the fingerprint.
  1. Click on the padlock icon and then click on Show connection details.
Google chrome website certificate ssl
  1. Then, click on Show certificate.
Google chrome website certificate ssl certificate is valid
  1. A new window will open with all the information about the website’s certificate, including the fingerprints. For the ESP8266 examples, you’ll use the SHA-1 fingerprint.
website fingerprint example

HTTPS Requests with the ESP8266 NodeMCU

Now that you know all the major important aspects of certificates and how to get a server’s certificate, let’s finally take a look at how to make HTTPS requests with the ESP8266 using the Arduino core. We’ll cover different methods: without a certificate, with the website fingerprint, and with the server’s root certificate.

HTTPS Requests with the ESP8266 NodeMCU board

You can find different examples showing how to make HTTPS requests with the ESP8266 in the Arduino IDE examples section.

  • Basic HTTPS Client (ESP8266HTTPClient library): File > Examples > ESP8266HTTPClient > BasicHTTPSClient
  • Basic HTTPS Client (WiFiClientSecure library): File > Examples > ESP8266WiFi > HTTPSRequest

You’ll need to update the certificates and fingerprints to make the examples work. We created several examples based on those. All examples presented make a request to the www.howsmyssl.com/a/check website. It returns some information regarding how secure the HTTPS connection is. Let’s take a look at them.

ESP8266 NodeMCU HTTPS Requests – No Certificate

You can make HTTPS requests with the ESP8266 without a certificate and without a fingerprint. The connection will be encrypted, but you’ll skip the SSL server certificate verification. This means that you won’t be sure if the server you’re connected to is really who it claims to be. This situation is useful for testing purposes or to make HTTPS requests to local servers inside your network.

The following code was based on the BasicHttpsClient example.

To test the code, simply insert your network credentials and upload the code to your board.

/*
  Complete project details: https://RandomNerdTutorials.com/esp8266-nodemcu-https-requests/ 
  Based on the BasicHTTPSClient.ino Created on: 20.08.2018 (ESP8266 examples)
*/

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureBearSSL.h>

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

void setup() {
  Serial.begin(115200);
  //Serial.setDebugOutput(true);

  Serial.println();
  Serial.println();
  Serial.println();

  //Connect to Wi-Fi
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi ..");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(1000);
  }
}

void loop() {
  // wait for WiFi connection
  if ((WiFi.status() == WL_CONNECTED)) {

    std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);

    // Ignore SSL certificate validation
    client->setInsecure();
    
    //create an HTTPClient instance
    HTTPClient https;
    
    //Initializing an HTTPS communication using the secure client
    Serial.print("[HTTPS] begin...\n");
    if (https.begin(*client, "https://www.howsmyssl.com/a/check")) {  // HTTPS
      Serial.print("[HTTPS] GET...\n");
      // start connection and send HTTP header
      int httpCode = https.GET();
      // httpCode will be negative on error
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        Serial.printf("[HTTPS] GET... code: %d\n", httpCode);
        // file found at server
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          String payload = https.getString();
          Serial.println(payload);
        }
      } else {
        Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
      }

      https.end();
    } else {
      Serial.printf("[HTTPS] Unable to connect\n");
    }
  }
  Serial.println();
  Serial.println("Waiting 2min before the next round...");
  delay(120000);
}

View raw code

How does the Code Work?

First, you need to include the required libraries. You need the WiFiClientSecureBearSSL library to make HTTPS requests.

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureBearSSL.h>

Insert your network credentials in the following lines.

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

In the setup(), initialize the Serial Monitor and connect the board to your Wi-Fi network.

void setup() {
  Serial.begin(115200);
  // Serial.setDebugOutput(true);

  Serial.println();
  Serial.println();
  Serial.println();

  //Connect to Wi-Fi
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi ..");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(1000);
  }

The following line creates a new WiFiClientSecure instance called client.

std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);

In case you don’t want to verify the server certificate, use the setInsecure() method on the client.

// Ignore SSL certificate validation
client->setInsecure();

Create an HTTPClient instance called https.

//create an HTTPClient instance
HTTPClient https;

Initialize the https client on the host specified using the begin() method. In this case, we’re making a request on the following URL: https://www.howsmyssl.com/a/check.

 if (https.begin(*client, "https://www.howsmyssl.com/a/check")) {  // HTTPS

Get the server response code.

 int httpCode = https.GET();

If the response code is a positive number, it means the connection was established successfully, so we can read the response payload using the getString() method on the https object. Then, we can print the payload in the Serial Monitor. In a practical application, you can do whatever task you need with the ESP8266 depending on the received payload.

if (https.begin(*client, "https://www.howsmyssl.com/a/check")) {  // HTTPS
  Serial.print("[HTTPS] GET...\n");
  // start connection and send HTTP header
  int httpCode = https.GET();
  // httpCode will be negative on error
  if (httpCode > 0) {
    // HTTP header has been send and Server response header has been handled
    Serial.printf("[HTTPS] GET... code: %d\n", httpCode);
    // file found at server
    if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
      String payload = https.getString();
      Serial.println(payload);
    }

If the response code is a negative number, it means we have an error. We’ll print the error code.

else {
   Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
}

Finally, close the HTTPS connection using the end() method:

https.end();

This specific example makes a request every two minutes. You should change it depending on your project requirements.

Serial.println("Waiting 2min before the next round...");
delay(120000);

Demonstration

After uploading the code, open the Serial Monitor at a baud rate of 115200. Press the on-board RST button to start running the newly uploaded code.

You should get something similar as shown in the picture below.

ESP8266 HTTPS example demonstration serial monitor

You get the response code 200, which means everything is fine with the request.

If you scroll to the right, you’ll get the result of how secure the connection is. You should get a “Probably Okay”.

ESP8266 HTTPS example demonstration serial monitor

Your connection is still encrypted, but with this example, it will skip SSL verification.

ESP8266 NodeMCU HTTPS Requests – Fingerprint

You can make HTTPS requests with the ESP8266, and check the server authenticity using the server fingerprint. One of the biggest downsides of using a fingerprint is that its validity is usually pretty short. So, you’ll need to update your sketch quite often.

Here’s an example using server verification with the fingerprint. This example is based on the BasicHttpsClient example. Because the fingerprint changes quite often, you may need to modify the code with the website’s current fingerprint—check this section to learn how to get the fingerprint.

/*
  Complete project details: https://RandomNerdTutorials.com/esp8266-nodemcu-https-requests/
  Based on the BasicHTTPSClient.ino Created on: 20.08.2018 (ESP8266 examples)
*/

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureBearSSL.h>

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// Fingerprint (might need to be updated)
const uint8_t fingerprint[20] = {0x76, 0x99, 0x2e, 0x6f, 0x04, 0xf4, 0xad, 0x19, 0xba, 0x54, 0xf5, 0x92, 0x50, 0x51, 0x56, 0x2b, 0x86, 0x8b, 0x5a, 0x92};

void setup() {
  Serial.begin(115200);
  //Serial.setDebugOutput(true);

  Serial.println();
  Serial.println();
  Serial.println();

  //Connect to Wi-Fi
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi ..");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(1000);
  }
}

void loop() {
  // wait for WiFi connection
  if ((WiFi.status() == WL_CONNECTED)) {

    std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);

    client->setFingerprint(fingerprint);
    // Or, if you happy to ignore the SSL certificate, then use the following line instead:
    // client->setInsecure();

    HTTPClient https;

    Serial.print("[HTTPS] begin...\n");
    if (https.begin(*client, "https://www.howsmyssl.com/a/check")) {  // HTTPS

      Serial.print("[HTTPS] GET...\n");
      // start connection and send HTTP header
      int httpCode = https.GET();

      // httpCode will be negative on error
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        Serial.printf("[HTTPS] GET... code: %d\n", httpCode);

        // file found at server
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          String payload = https.getString();
          Serial.println(payload);
        }
      } else {
        Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
      }

      https.end();
    } else {
      Serial.printf("[HTTPS] Unable to connect\n");
    }
  }

  Serial.println();
  Serial.println("Waiting 2min before the next round...");
  delay(120000);
}

View raw code

How does the Code Work?

The code in this example is very similar to the previous one but adds the necessary lines to check the server fingerprint. We’ll just take a quick look at the lines relevant for this example. For a more detailed explanation, check the previous example.

First, you need to include the required libraries. You need the WiFiClientSecureBearSSL library to make HTTPS requests.

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureBearSSL.h>

Insert your network credentials in the following lines:

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

Insert the server fingerprint in the following line:

// Fingerprint for demo URL (might need to be updated)
const uint8_t fingerprint[20] = {0x76, 0x99, 0x2e, 0x6f, 0x04, 0xf4, 0xad, 0x19, 0xba, 0x54, 0xf5, 0x92, 0x50, 0x51, 0x56, 0x2b, 0x86, 0x8b, 0x5a, 0x92};

In a previous section, we’ve seen that the fingerprint for the URL we’ll make the request is:

76 99 2E 6F 04 F4 AD 19 BA 54 F5 92 50 51 56 2B 86 8B 5A 92
website fingerprint example

So, you must insert it in your code like this:

const uint8_t fingerprint[20] = {0x76, 0x99, 0x2e, 0x6f, 0x04, 0xf4, 0xad, 0x19, 0xba, 0x54, 0xf5, 0x92, 0x50, 0x51, 0x56, 0x2b, 0x86, 0x8b, 0x5a, 0x92};

Because the fingerprint changes frequently, you may need to double-check the current fingerprint. If you’re making a request on a different URL, you need to get its fingerprint as described previously.

You need to create a WiFiClientSecure instance called client.

std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);

To set the server fingerprint, use the setFingerpirnt() method on the client and pass the fingerprint as an argument:

client->setFingerprint(fingerprint);

Create an HTTPClient instance called https.

//create an HTTPClient instance
HTTPClient https;

Initialize the https client on the host specified using the begin() method. In this case, we’re making a request on the following URL: https://www.howsmyssl.com/a/check.

 if (https.begin(*client, "https://www.howsmyssl.com/a/check")) {  // HTTPS

Then, you just need to handle the server response. A response code of 200 means everything went as expected. A response code with a negative number means something went wrong with the request.

 int httpCode = https.GET();

// httpCode will be negative on error
if (httpCode > 0) {
  // HTTP header has been send and Server response header has been handled
  Serial.printf("[HTTPS] GET... code: %d\n", httpCode);

  // file found at server
  if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
    String payload = https.getString();
    Serial.println(payload);
  }
} else {
  Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
}

Demonstration

After uploading the code, open the Serial Monitor at a baud rate of 115200. Press the on-board RST button to start running the newly uploaded code.

You should get something similar as shown in the picture below (exactly like in the previous example).

ESP8266 HTTPS example demonstration serial monitor

You get the response code 200, which means everything is fine with the request.

If you scroll to the right, you’ll get the result of how secure the connection is. You should get a “Probably Okay”.

ESP8266 HTTPS example demonstration serial monitor

Your connection is encrypted and you verified the authenticity of the server using the server fingerprint.

ESP8266 NodeMCU HTTPS Requests – Root Certificate

In this section, we’ll show you an example of an HTTPS request using the server root certificate.

Using the server root certificate is a great option because you verify the server SSL certificate, and thus you guarantee you’re communicating with the right server. Additionally, the root certificate is usually valid for more than five years, which means you don’t need to constantly update your ESP8266 sketch (unlike the fingerprint method).

We’re providing an example based on the ESP8266_HTTPSRequest example, which you can find in your Arduino IDE: File Examples ESP8266WiFi HTTPSRequest.

/*
  Complete project details: https://RandomNerdTutorials.com/esp8266-nodemcu-https-requests/
  Based on the example created by Ivan Grokhotkov, 2015 (File > Examples > ESP8266WiFi > HTTPSRequests)
*/

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <ESP8266HTTPClient.h>

// Root certificate for howsmyssl.com
const char IRG_Root_X1 [] PROGMEM = R"CERT(
-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
-----END CERTIFICATE-----
)CERT";

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// Create a list of certificates with the server certificate
X509List cert(IRG_Root_X1);

void setup() {
  Serial.begin(115200);
  //Serial.setDebugOutput(true);

  Serial.println();
  Serial.println();
  Serial.println();

  //Connect to Wi-Fi
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print("Connecting to WiFi ..");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print('.');
    delay(1000);
  }

  // Set time via NTP, as required for x.509 validation
  configTime(3 * 3600, 0, "pool.ntp.org", "time.nist.gov");

  Serial.print("Waiting for NTP time sync: ");
  time_t now = time(nullptr);
  while (now < 8 * 3600 * 2) {
    delay(500);
    Serial.print(".");
    now = time(nullptr);
  }
  Serial.println("");
  struct tm timeinfo;
  gmtime_r(&now, &timeinfo);
  Serial.print("Current time: ");
  Serial.print(asctime(&timeinfo));
}

void loop() {
  WiFiClientSecure client;

  // wait for WiFi connection
  if ((WiFi.status() == WL_CONNECTED)) {

    client.setTrustAnchors(&cert);

    HTTPClient https;

    Serial.print("[HTTPS] begin...\n");
    if (https.begin(client, "https://www.howsmyssl.com/a/check")) {  // HTTPS

      Serial.print("[HTTPS] GET...\n");
      // start connection and send HTTP header
      int httpCode = https.GET();

      // httpCode will be negative on error
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        Serial.printf("[HTTPS] GET... code: %d\n", httpCode);

        // file found at server
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          String payload = https.getString();
          Serial.println(payload);
        }
      } else {
        Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
      }

      https.end();
    } else {
      Serial.printf("[HTTPS] Unable to connect\n");
    }
  }

  Serial.println();
  Serial.println("Waiting 2min before the next round...");
  delay(10000);
}

View raw code

This example does exactly the same thing as the previous ones (makes a request to the www.howsmyssl.com website), but it checks the server certificate. You can make a request to any other website, as long as you get its server certificate.

For this section, you’ll need the server certificate (see this section to learn how to get the server certificate).

How does the Code Work?

This example is similar to the previous ones but adds the required lines to check the server certificate.

First, include the required libraries. You’ll use the WiFiClientSecure library to make requests using TLS, and the ESP8266HTTPClient library to make it easy to make the requests.

#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <ESP8266HTTPClient.h>

The server root certificate for the howsmyssl.com website is saved on the IRG_Root_X1 variable.

// Root certificate for howsmyssl.com
const char IRG_Root_X1 [] PROGMEM = R"CERT(
-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
-----END CERTIFICATE-----
)CERT";

Insert your network credentials in the following lines:

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

Then, you need to create a list of certificates cert (even if you only have one certificate) with the server certificate you want to use:

// Create a list of certificates with the server certificate
X509List cert(IRG_Root_X1);

In the setup(), you need to configure the time on the ESP8266, which is necessary to validate the certificate.

// Set time via NTP, as required for x.509 validation
configTime(3 * 3600, 0, "pool.ntp.org", "time.nist.gov");

Serial.print("Waiting for NTP time sync: ");
time_t now = time(nullptr);
while (now < 8 * 3600 * 2) {
  delay(500);
  Serial.print(".");
  now = time(nullptr);
}
Serial.println("");
struct tm timeinfo;
gmtime_r(&now, &timeinfo);
Serial.print("Current time: ");
Serial.print(asctime(&timeinfo));

First, to make an HTTPS request, you need to create a WiFiClientSecure object.

WiFiClientSecure client;

Then, you need to tell which certificates the client can trust using the setTrustAnchors() method and passing as an argument the certificate list cert (in this case, we only added one certificate).

client.setTrustAnchors(&cert);

From now on, the code is the same as the previous projects.

You need to create an HTTPClient instance (https), initialize the https client on the host specified using the begin() method, and then, handle the server response.

client.setTrustAnchors(&cert);

HTTPClient https;

Serial.print("[HTTPS] begin...\n");
if (https.begin(client, "https://www.howsmyssl.com/a/check")) {  // HTTPS

  Serial.print("[HTTPS] GET...\n");
  // start connection and send HTTP header
  int httpCode = https.GET();

 
 // httpCode will be negative on error
  if (httpCode > 0) {
    // HTTP header has been send and Server response header has been handled
    Serial.printf("[HTTPS] GET... code: %d\n", httpCode);

     // file found at server
    if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
      String payload = https.getString();
      Serial.println(payload);
    }
  } else {
    Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
  }

After uploading this code to the ESP8266 board, you should get the same messages on the Serial Monitor as in the previous examples.

ESP8266 HTTPS Requests Serial Monitor

ESP8266 HTTPS Requests – Root Store

Instead of just saving one certificate on the ESP8266, you can save multiple certificates. You can add two, three, or more certificates, and you can even add a root store. As we’ve seen previously, a root store is a database of root certificates that your browser or operating system can trust.

You can download the entire Mozilla Certificate store, and upload it to your ESP8266 so that it behaves like a browser. So, you’ll be able to make HTTPS requests securely to any server (that uses TLS) without having to hardcode its certificate.

This article is already quite long, so we’ll cover this subject in another tutorial (to be published soon).

If you’re curious about this topic, I recommend taking a look at the ESP8266 Certificate Store official example: BearSSL_CertStore. You can also find it on your Arduino IDE: File > Examples > ESP8266WiFi > BearSSL_CertStore.

Wrapping Up

In this tutorial, you learned how to make HTTPS requests with the ESP8266.

We’ve shown you different ways to make HTTPS requests with the ESP8266: without a certificate, with a fingerprint, and with a certificate. It’s also possible to use multiple certificates or a root store—we’ll cover this subject in a future tutorial. You also learned about the basic concepts of HTTPS protocol and about SSL/TLS certificates.

Other related tutorials that you may find interesting:

We hope you found this tutorial useful. We intend to create more tutorials about HTTPS and secure communication. Let us know in the comments below what you think.

Learn more about the ESP8266 with our resources:

Thanks for reading.



Build Web Server projects with the ESP32 and ESP8266 boards to control outputs and monitor sensors remotely. Learn HTML, CSS, JavaScript and client-server communication protocols DOWNLOAD »

Build Web Server projects with the ESP32 and ESP8266 boards to control outputs and monitor sensors remotely. Learn HTML, CSS, JavaScript and client-server communication protocols DOWNLOAD »

Recommended Resources

Build a Home Automation System from Scratch » With Raspberry Pi, ESP8266, Arduino, and Node-RED.

Home Automation using ESP8266 eBook and video course » Build IoT and home automation projects.

Arduino Step-by-Step Projects » Build 25 Arduino projects with our course, even with no prior experience!

What to Read Next…


Enjoyed this project? Stay updated by subscribing our newsletter!

5 thoughts on “ESP8266 NodeMCU HTTPS Requests (Arduino IDE)”

  1. Hello
    I’m new to programming. How can I add two or more certificates? Thanks

    At this step:

    Then, you need to create a list of certificates cert (even if you only have one certificate) with the server certificate you want to use:
    // Create a list of certificates with the server certificate
    X509List cert(IRG_Root_X1);

    Reply

Leave a Comment

Download Our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.