ESP8266: HTTP POST Requests

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 at Ebay for less than 5 euros.

If you prefer a video tutorial, please check my YouTube Channel below.

The setup

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

We will need the ESP8266WiFi.h, so we can connect the ESP8266 to a WiFi network, and the ESP8266HTTPClient.h, which makes available the methods needed to perform the POST request.

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

In the Arduino setup function, we will start by initializing a serial connection, so we can output the results of our program.

Serial.begin(115200);

After that, we will take care of connecting the ESP8266 to a WiFi network, so later we can send the HTTP request. To do so, we only need to call the begin method on the WiFi extern variable, passing as first input the name of the network (SSID) and as second the password. Note that, in the snippet below, I’m using placeholder strings that you should replace by your network credentials.

For a detailed tutorial on how to connect a ESP8266 to a WiFi network, please check here.

WiFi.begin("yourSSID", "yourPASS"); 

To finish the setup function, we will poll the status of the WiFi connection until it is established. We are using a polling approach here for simplicity, since we can only start doing the HTTP POST requests after the connection to the WiFi network is established. Naturally, in a real application, we should take in consideration that there might be some issue trying to connect to the network and that polling might not be the best approach for the requirements.

The complete setup function can be seen below.

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");

  }

}

The main code

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

First of all, we need to define an object of 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 will call the begin method on the http object and pass the URL that we want to connect to and make the HTTP 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 used in the code snippet implements a dummy REST API for testing and prototyping).

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

Next, we can define headers for the request 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 it is important to check for error handling.

Take in consideration that, if the value is greater than 0, it corresponds to a standard HTTP code. If this value is lesser than 0, it corresponds to a ESP8266 error, related with the connection. You can check the list of possible errors here.

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();

We will print both the received payload and the HTTP code.

Serial.println(httpCode);
Serial.println(payload);

To finish, we need to call the end method on the http object to guarantee that the TCP connection is closed. This is very important to free the resources.

http.end();

The final code is shown bellow. To handle any possible WiFi connection errors, we will include a validation of the connection status before making the request. We will also add a 30 seconds delay between each iteration of the Arduino loop, to avoid a constant polling of the server.

Note that, to keep the code simpler and focus on the main subject of sending the HTTP POST request, we did not check if the httpCode variable 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 MuleSoft 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 application receiving HTTP POST from ESP8266
Figure 1 – Output of the MuleSoft 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.

Output of the ESP8266 POST Request program, on the Arduino IDE serial monitor
Figure 2 – Output of the POST requests.

To avoid having to setup your own server to test the ESP8266 code, you can simply send the request to the testing API suggested in the previous section.

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 code section:

http.writeToStream(&Serial);

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

Technical details

  • ESP8266 libraries: v2.3.0.
  • Operating system: Windows 8.1

Related Posts

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 Leo Leow Cancel reply

%d bloggers like this: