ESP8266: HTTP POST Requests

The objective of this post is to explain how to do POST requests from an ESP8266, using the Arduino IDE and the ESP8266 libraries.


Introduction

The objective of this post is to explain how to do POST requests from an ESP8266, using the Arduino IDE and the ESP8266 libraries. All the tests shown here were performed on a NodeMCU board, which you can find here at eBay for less than 5 euros.

If you prefer a video tutorial, please check the video bellow on my YouTube Channel.


The setup

First, we need to include some libraries, which should be available after the installation of the ESP8266 libraries for the Arduino IDE.

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

In the setup function, we will just initialize the Serial connection, in order to print the results of our application. Besides that, we need to establish a connection to an AP (Access Point), so the ESP8266 will be able to make the HTTP Requests. The code is specified bellow.

void setup() {

  Serial.begin(115200);                 //Serial connection
  WiFi.begin("yourSSID", "yourPASS");   //WiFi connection

  while (WiFi.status() != WL_CONNECTED) {  //Wait for the WiFI connection completion

    delay(500);
    Serial.println("Waiting for connection");

  }

}

For more details on how to connect to a WiFi network, check this previous post.


The main code

In this section, we will analyze the code needed in the main loop function to perform the POST request. We will break the code and analyze the most relevant parts step by step, but the final code is summarized at the end of the section.

First of all, we need to declare an object of the class HTTPClient, from which we will call various methods to prepare the headers and content of the request, send it and check for the result. We will call this object simply “http”.

HTTPClient http;

After that, we call the begin method on the http object and pass the URL that we want to connect to and make the post request. In this case, I’m sending the post request to an application running on my local network, which is why I’m sending it the format seen bellow (Host IP:Port/Path).

http.begin("http://192.168.1.88:9999/hello");

Nevertheless, we can send the request to a website by specifying it’s domain name, as seen bellow (the destination website specified implements a dummy REST API for testing and prototyping).

http.begin("http://jsonplaceholder.typicode.com/users");

Next, we can define headers with the addHeader method. In this case, we are specifying the content-type as “text/plain”, since we will just send a simple string in the body.

http.addHeader("Content-Type", "text/plain");

The body of the request is specified as a parameter when calling the POST method on the HTTPClient object. In this case, we will simply send a string saying “Message from ESP8266”. The return value of this method corresponds to the HTTP response code and thus is important to check for error handling.

int httpCode = http.POST("Message from ESP8266");

We can now get the payload by calling the getString method, which will return the response payload as a string.

String payload = http.getString();

In the end, we need to call the end() method on the object to guarantee that the TCP connection is closed. This is very important to free the resources.

http.end();

Just to handle any possible WiFi connection errors, we will include a validation of the connection status before making the request. For debugging purposes, we will print both the response payload and the HTTP code.

The final code is specified bellow. To keep the code simpler and focus on the main subject, we did not check if the httpCode is less than zero, which indicates an error in the connection. Nevertheless, we should do so in the final code of an application.

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

void setup() {

  Serial.begin(115200);                                  //Serial connection
  WiFi.begin("yourSSID", "yourPASS");   //WiFi connection

  while (WiFi.status() != WL_CONNECTED) {  //Wait for the WiFI connection completion

    delay(500);
    Serial.println("Waiting for connection");

  }

}

void loop() {

 if(WiFi.status()== WL_CONNECTED){   //Check WiFi connection status

   HTTPClient http;    //Declare object of class HTTPClient

   http.begin("http://192.168.1.88:8085/hello");      //Specify request destination
   http.addHeader("Content-Type", "text/plain");  //Specify content-type header

   int httpCode = http.POST("Message from ESP8266");   //Send the request
   String payload = http.getString();                  //Get the response payload

   Serial.println(httpCode);   //Print HTTP return code
   Serial.println(payload);    //Print request response payload

   http.end();  //Close connection

 }else{

    Serial.println("Error in WiFi connection");   

 }

  delay(30000);  //Send a request every 30 seconds

}

 

Testing the code

In the context of this tutorial, I was sending the post requests to a mule application running in a machine on my local network. Just to illustrate the result, figure 1 shows the output of incoming requests on the console of the development environment. As can be seen in the bottom right, it is printing the “Message from ESP8266” string we defined early.

Mulesoft receiving post from ESP8266

Figure 1 – Output of the mule application that is receiving the POST requests.

Figure 2 shows the HTTP codes and response payloads for the POST requests. In this case, I defined a simple “Message received” string as response to the requests.

ESP8266 HTTP Post response

Figure 2 – Output of the POST requests.


Final Notes

As an alternative, the begin method used before can be called with other sets of parameters, as can be seen in the specification of the HTTPClient class. For example, we can pass the host IP, port and path as 3 different parameters, instead of a single string, amongst many other options.

The HTTPClient class also has a method to simplify debugging of a response to the request. So, if we want to print the response payload to the serial port, we can just call the writeToStream method and pass as argument a pointer to the Serial port, that we initialized before in the setup function. So, the call bellow is an alternative to the getString method used in the example:

http.writeToStream(&Serial);

These are just 2 alternative implementation examples. The HTTPClient class many other useful methods not used in this tutorial. You can check them here.


Technical details

ESP8266 libraries: v2.3.0.

240 thoughts on “ESP8266: HTTP POST Requests”

  1. Hi,I want to make an android app that can control rgb led through esp8266 with json format.how do I do that?

    1. Hi! It depends on the architecture you want to implement, but I would say something like this would work fine:

      – You need to have the ESP listening for incoming HTTP requests, so you can receive commands to control your RGB LED. You can check here how to configure the ESP to work as a simple HTTP web server.
      https://techtutorialsx.wordpress.com/2016/10/03/esp8266-setting-a-simple-http-webserver/

      – Then, if you want to use JSON, you need to be able to parse incoming JSON data. You can check how to do that in the ESP here.
      https://techtutorialsx.wordpress.com/2016/07/30/esp8266-parsing-json/

      Naturally, you will need to implement the functions to control the LED and the android app.

      Hope it helps, let me know if you need more help.

  2. Hi,I want to make an android app that can control rgb led through esp8266 with json format.how do I do that?

    1. Hi! It depends on the architecture you want to implement, but I would say something like this would work fine:
      – You need to have the ESP listening for incoming HTTP requests, so you can receive commands to control your RGB LED. You can check here how to configure the ESP to work as a simple HTTP web server.
      https://techtutorialsx.wordpress.com/2016/10/03/esp8266-setting-a-simple-http-webserver/
      – Then, if you want to use JSON, you need to be able to parse incoming JSON data. You can check how to do that in the ESP here.
      https://techtutorialsx.wordpress.com/2016/07/30/esp8266-parsing-json/
      Naturally, you will need to implement the functions to control the LED and the android app.
      Hope it helps, let me know if you need more help.

  3. Hi.
    Presently i am able to send http POST requests and receive the request in a php page which i hosted on other system using nodemcu esp8266 12-E board.Now I connected mpu6050 sensor to nodemcu and receive the mpu6050 sensor values in the php file like i received the previous request but i am not getting the real time sensor readings.Can u provide me the correct coding.

    1. Hi!
      Sorry I don’t know if I understood your problem. You are sending the POST request from a nodemcu board and you have a system that has a PHP page, right?

      Are you getting the correct values from the sensor on the nodemcu, before actually sending them to the PHP page? If not, that should be the first debug step: getting the values and printing them to the serial port, to check if they are ok.

      Then, how are you sending the values in the POST request? In the body of the request or in the URL? Also, are you sending just raw values (directly the values you get from the sensor) or using some type of protocol, such as JSON or XML?

      Then, is your PHP code expecting to receive the sensor values in the format you are sending from the nodemcu?

      There are too many variables, you should divide the debugging in steps to isolate the cause of your problem.

  4. Hi.
    Presently i am able to send http POST requests and receive the request in a php page which i hosted on other system using nodemcu esp8266 12-E board.Now I connected mpu6050 sensor to nodemcu and receive the mpu6050 sensor values in the php file like i received the previous request but i am not getting the real time sensor readings.Can u provide me the correct coding.

    1. Hi!
      Sorry I don’t know if I understood your problem. You are sending the POST request from a nodemcu board and you have a system that has a PHP page, right?
      Are you getting the correct values from the sensor on the nodemcu, before actually sending them to the PHP page? If not, that should be the first debug step: getting the values and printing them to the serial port, to check if they are ok.
      Then, how are you sending the values in the POST request? In the body of the request or in the URL? Also, are you sending just raw values (directly the values you get from the sensor) or using some type of protocol, such as JSON or XML?
      Then, is your PHP code expecting to receive the sensor values in the format you are sending from the nodemcu?
      There are too many variables, you should divide the debugging in steps to isolate the cause of your problem.

  5. Hi,Thanks for replying.

    Yeah exactly i have a system with a PHP page where i want to send the http POST requests.I am able to send normal messages to the page.My task is to send the sensor values which is connected to nodmcu development board continuously to the php page using arduino IDE. Previously i have the send the sensor values to the system using a firmware called devicehive cloud. There is a html page where it receives requests from the nodemcu to which mpu6050 sensor is connected and values are displayed but it is taking requests very slowly at a rate of 10s approximately.I wanted to send continuous request for every 1 to 2seconds where i can do it from arduino ide using your code.Can u provide me a similar type of example code like any sensor so that i can send the sensor values continuously. Ultimately i wanted to set the sensor to a threshold where it can give an alert when it experiences a motion beyond certain threshold set in the code.

    1. Hi!

      Well, I cannot give you an exact code because you should send the content in a format that your PHP page will understand, and I don’t know what format it uses.

      Are you posting the exact value you get from the sensor? Like, if the sensor returns “10”, the body of your POST request is “10”? Or are you using a protocol like JSON?

      The interval you have to send the readings of the sensor is defined by you, right? In pseudo code, you should do something like:

      While (1){
      x = getSensorValue();
      sendHTTPrequest(x);
      delay(interval);
      }

      If the requests are taking to much time, maybe there is some problem in the PHP code. Can you measure the execution time of the code in the PHP page, between receiving the request from the Nodemcu and answering the request?

      Also, if you want something near real time, you would have better performance by opening a socket to the server, maintaining it open and sending the data in a simpler protocol. HTTP has much more overhead in the quantity of data sent and you are opening and closing a connection each time you send a request, which makes it slower.

      You can also use something like MQTT, for example.

  6. Hi,Thanks for replying.
    Yeah exactly i have a system with a PHP page where i want to send the http POST requests.I am able to send normal messages to the page.My task is to send the sensor values which is connected to nodmcu development board continuously to the php page using arduino IDE. Previously i have the send the sensor values to the system using a firmware called devicehive cloud. There is a html page where it receives requests from the nodemcu to which mpu6050 sensor is connected and values are displayed but it is taking requests very slowly at a rate of 10s approximately.I wanted to send continuous request for every 1 to 2seconds where i can do it from arduino ide using your code.Can u provide me a similar type of example code like any sensor so that i can send the sensor values continuously. Ultimately i wanted to set the sensor to a threshold where it can give an alert when it experiences a motion beyond certain threshold set in the code.

    1. Hi!
      Well, I cannot give you an exact code because you should send the content in a format that your PHP page will understand, and I don’t know what format it uses.
      Are you posting the exact value you get from the sensor? Like, if the sensor returns “10”, the body of your POST request is “10”? Or are you using a protocol like JSON?
      The interval you have to send the readings of the sensor is defined by you, right? In pseudo code, you should do something like:
      While (1){
      x = getSensorValue();
      sendHTTPrequest(x);
      delay(interval);
      }
      If the requests are taking to much time, maybe there is some problem in the PHP code. Can you measure the execution time of the code in the PHP page, between receiving the request from the Nodemcu and answering the request?
      Also, if you want something near real time, you would have better performance by opening a socket to the server, maintaining it open and sending the data in a simpler protocol. HTTP has much more overhead in the quantity of data sent and you are opening and closing a connection each time you send a request, which makes it slower.
      You can also use something like MQTT, for example.

  7. Hi
    I want to send the sensor readings to the PHP page in other system.Is there any such type of example such that the sensor values are displayed in the webpage via sending POST requests using arduino ide.

    1. Hi. I usually use Python for implementing the back-end systems, so I don’t have any example with PHP.

      I have an example on how to send data to a Python Flask application. You may be able to adapt it:
      https://techtutorialsx.com/2017/01/08/esp8266-posting-json-data-to-a-flask-server-on-the-cloud/

      I think it will be hard to find a specific example in the web that sends sensor readings to a PHP page via POST and shows the values in a webpage.

      I think the best way is to divide the problem in peaces and find examples for each one. That way you can figure out how each peace of your final system works and then link everything together.

      1. Hi

        The above code which u provided where we sending an arbitrary message (“Hello World”),Can’t we edit the code in such a way that sensor sends a POST request to the php page in other sysytem or server whenever it exceeds certain tolerance.I have no idea using MQTT .Can u help me to sort it out

        1. Hi! Yes, you just need to pass the value to the function. I think a simple conversion to string is enough. But are you having difficulty with the logic of the program or with the HTTP functions?

          int x = getSensorValue();

          if (x> thresholdValue){

          HTTPClient http; //Declare object of class HTTPClient

          http.begin(“yourSite”); //Specify request destination
          http.addHeader(“Content-Type”, “text/plain”); //Specify content-type header

          http.POST(String(x));
          String payload = http.getString();

          http.end(); //Close connection

          }

          You can check more on string conversions here:
          https://www.arduino.cc/en/Reference/StringConstructor

          1. Hi
            I want to get the sensor readings from mpu6050 to nodemcu and it has to send a POST request.
            Currently i am able to send an arbitrary message from Nodemcu to PHP page on a computer but i need to get the sensor readings from mpu6050 to Nodmcu.

  8. Hi
    I want to send the sensor readings to the PHP page in other system.Is there any such type of example such that the sensor values are displayed in the webpage via sending POST requests using arduino ide.

    1. Hi. I usually use Python for implementing the back-end systems, so I don’t have any example with PHP.
      I have an example on how to send data to a Python Flask application. You may be able to adapt it:
      https://techtutorialsx.com/2017/01/08/esp8266-posting-json-data-to-a-flask-server-on-the-cloud/
      I think it will be hard to find a specific example in the web that sends sensor readings to a PHP page via POST and shows the values in a webpage.
      I think the best way is to divide the problem in peaces and find examples for each one. That way you can figure out how each peace of your final system works and then link everything together.

      1. Hi
        The above code which u provided where we sending an arbitrary message (“Hello World”),Can’t we edit the code in such a way that sensor sends a POST request to the php page in other sysytem or server whenever it exceeds certain tolerance.I have no idea using MQTT .Can u help me to sort it out

        1. Hi! Yes, you just need to pass the value to the function. I think a simple conversion to string is enough. But are you having difficulty with the logic of the program or with the HTTP functions?
          int x = getSensorValue();
          if (x> thresholdValue){
          HTTPClient http; //Declare object of class HTTPClient
          http.begin(“yourSite”); //Specify request destination
          http.addHeader(“Content-Type”, “text/plain”); //Specify content-type header
          http.POST(String(x));
          String payload = http.getString();
          http.end(); //Close connection
          }
          You can check more on string conversions here:
          https://www.arduino.cc/en/Reference/StringConstructor

          1. Hi
            I want to get the sensor readings from mpu6050 to nodemcu and it has to send a POST request.
            Currently i am able to send an arbitrary message from Nodemcu to PHP page on a computer but i need to get the sensor readings from mpu6050 to Nodmcu.

  9. Hi! Thanks for creating this — your tutorial have been very helpful.

    I keep on getting a -1 as the httpCode from the server. Here’s what my code looks like:

    void loop() {
    if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    http.begin(“http://pi.local:8000/planner/test-light/”);
    Serial.println(“Connected to HTTPClient”);
    http.addHeader(“Content-Type”, “text/plain”);
    int httpCode = http.POST(“test”);
    String payload = http.getString();
    Serial.println(httpCode);
    Serial.println(payload);
    http.end();
    }
    delay(5000);
    }

    I’ve tried making a post request from another computer using CURL and it works fine. Any idea what the problem could be?

    I saw your GET post request and that worked fine.

    Thanks for any help!

    1. Hi! Thanks for your feedback, I’m glad you are finding the content useful 🙂

      One thing that may be the reason for the issue is that you are exposing your webserver using mdns. Or at least it is what it seems, since you have a .local domain.

      Can you find what is the actual IP of your server and change the pi.local by the IP in the begin method? That would be my first suggestion. It may worked fine with CURL because your computer was able to do mdns resolution and the ESP8266 was not.

      For the Get request example, did you use the website provided in the post or did you already use the pi.local? If it worked with the pi.local, then the problem should be other.

      Let me know if it helps

  10. Hi! Thanks for creating this — your tutorial have been very helpful.
    I keep on getting a -1 as the httpCode from the server. Here’s what my code looks like:
    void loop() {
    if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    http.begin(“http://pi.local:8000/planner/test-light/”);
    Serial.println(“Connected to HTTPClient”);
    http.addHeader(“Content-Type”, “text/plain”);
    int httpCode = http.POST(“test”);
    String payload = http.getString();
    Serial.println(httpCode);
    Serial.println(payload);
    http.end();
    }
    delay(5000);
    }
    I’ve tried making a post request from another computer using CURL and it works fine. Any idea what the problem could be?
    I saw your GET post request and that worked fine.
    Thanks for any help!

    1. Hi! Thanks for your feedback, I’m glad you are finding the content useful 🙂
      One thing that may be the reason for the issue is that you are exposing your webserver using mdns. Or at least it is what it seems, since you have a .local domain.
      Can you find what is the actual IP of your server and change the pi.local by the IP in the begin method? That would be my first suggestion. It may worked fine with CURL because your computer was able to do mdns resolution and the ESP8266 was not.
      For the Get request example, did you use the website provided in the post or did you already use the pi.local? If it worked with the pi.local, then the problem should be other.
      Let me know if it helps

  11. Hi, thanks for the like! It means so much.. But I have a question related to this post. How would I POST a form-data, by setting http.addHeader(“Content-Type”, “multipart/form-data”); ? How would I set the payload? Thank you!

  12. Hi, thanks for the like! It means so much.. But I have a question related to this post. How would I POST a form-data, by setting http.addHeader(“Content-Type”, “multipart/form-data”); ? How would I set the payload? Thank you!

  13. Hi! You’re welcome 🙂 Well I never tried doing a post request using that content type.

    But I think it should work if you send a string with the content respecting the format you need for that content type. That string is passed to the POST method.

    For example, when I’m sending application/json content, I just pass a string with the JSON to the POST method (example bellow).
    https://techtutorialsx.com/2017/01/08/esp8266-posting-json-data-to-a-flask-server-on-the-cloud/

  14. Hi! You’re welcome 🙂 Well I never tried doing a post request using that content type.
    But I think it should work if you send a string with the content respecting the format you need for that content type. That string is passed to the POST method.
    For example, when I’m sending application/json content, I just pass a string with the JSON to the POST method (example bellow).
    https://techtutorialsx.com/2017/01/08/esp8266-posting-json-data-to-a-flask-server-on-the-cloud/

  15. Hi Lukas
    I am also working on a similar project. Could you please share your project code or if there is any blog you have posted about it

  16. Hi Lukas
    I am also working on a similar project. Could you please share your project code or if there is any blog you have posted about it

    1. Hi! Sorry but I haven’t yet tried to send pictures / images from the ESP8266 to a webserver. Nevertheless, we’re you able to store it on the ESP8266?

    1. Hi! Sorry but I haven’t yet tried to send pictures / images from the ESP8266 to a webserver. Nevertheless, we’re you able to store it on the ESP8266?

    1. Hi! I never ran into that issue but I don’t recall having tried a request with a payload so big.

      I’ve been taking a quick look to the source file where that error code is generated but I didn’t find any limitation in the size on the code, such as a limiting variable or so:
      https://github.com/esp8266/Arduino/blob/2d9e7676309506da9be6e9bf0e1e7a3d7356d8f5/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp

      My guess is that it may be exceeding any limit on the lower level API calls.

      Also from this thread, it seems like a work around is sending the data in chunks, although it requires using the WiFi client (same as socket connection) for sending the data in parts.
      https://github.com/esp8266/Arduino/issues/1872

      But my suggestion is that you ask around the GitHub page for checking if someone ran into the same issue.

      If I find some more information meanwhile I will share here.

      Best regards,
      Nuno Santos

      1. I’ve checked that link you provided while doing some research on this topic but couldn’t find a solution.

        Currently I’m sending multiple posts as it was easier for me on this project but in the future I’ll look deeper into this. If I find anything I’ll post here.

        Thanks a lot for your answer!

    1. Hi! I never ran into that issue but I don’t recall having tried a request with a payload so big.
      I’ve been taking a quick look to the source file where that error code is generated but I didn’t find any limitation in the size on the code, such as a limiting variable or so:
      https://github.com/esp8266/Arduino/blob/2d9e7676309506da9be6e9bf0e1e7a3d7356d8f5/libraries/ESP8266HTTPClient/src/ESP8266HTTPClient.cpp
      My guess is that it may be exceeding any limit on the lower level API calls.
      Also from this thread, it seems like a work around is sending the data in chunks, although it requires using the WiFi client (same as socket connection) for sending the data in parts.
      https://github.com/esp8266/Arduino/issues/1872
      But my suggestion is that you ask around the GitHub page for checking if someone ran into the same issue.
      If I find some more information meanwhile I will share here.
      Best regards,
      Nuno Santos

      1. I’ve checked that link you provided while doing some research on this topic but couldn’t find a solution.
        Currently I’m sending multiple posts as it was easier for me on this project but in the future I’ll look deeper into this. If I find anything I’ll post here.
        Thanks a lot for your answer!

Leave a Reply to João Henrique Franco Cancel reply

%d bloggers like this: