The ESP8266 and ESP32 have both a fully implemented TCP/IP stack and are capable of sending request and handling responses from a server using the HTTP protocol.
In this project we will demonstrate how to send data to a server and request data from a server using the ESP8266 as a client and printing the response on a serial terminal
- Information: HTTP
- GET vs. POST request – What is the difference?
- Materials needed
- Example 1: HTTP GET request with ESP8266
- Example 2: HTTP POST request with ESP8266
- Testing
- Wrap-Up
1) Information: HTTP
The Hypertext Transfer Protocol (HTTP) is an application-level protocol for distributed, collaborative, hypermedia information systems. This is the foundation for data communication for the World Wide Web (i.e. internet) since 1990. HTTP is a generic and stateless protocol which can be used for other purposes as well using extensions of its request methods, error codes, and headers. The HTTP protocol is a request/response protocol based on the client/server based architecture where web browsers, robots and search engines, etc. act like HTTP clients, and the Web server acts as a server.
HTTP works as a request-response protocol between a client and server. Each Hypertext Transfer Protocol (HTTP) message is either a request or a response. A server listens on a connection for a request, parses each message received, interprets the message semantics in relation to the identified request target, and responds to that request with one or more response messages. A client constructs request messages to communicate specific intentions, examines received responses to see if the intentions were carried out, and determines how to interpret the results.
Client
The HTTP client sends a request to the server in the form of a request method, URI, and protocol version, followed by a MIME-like message containing request modifiers, client information, and possible body content over a TCP/IP connection.
Server
The HTTP server responds with a status line, including the message’s protocol version and a success or error code, followed by a MIME-like message containing server information, entity meta information, and possible entity-body content.
2) GET vs. POST request – What is the difference?
Requests in HTML can use either GET or POST method by specifying method=”POST” or method=”GET” (default) in the <form> element. The method specified determines how form data is submitted to the server. When the method is GET, all form data is encoded into the URL, appended to the action URL as query string parameters. With POST, form data appears within the message body of the HTTP request.
Here is an overview of the main differences of both request methods.
GET Request | POST Request | |
History | Parameters remain in browser history because they are part of the URL | Parameters are not saved in browser history. |
---|---|---|
Bookmarked | Can be bookmarked. | Can not be bookmarked. |
BACK button/re-submit behaviour | GET requests are re-executed but may not be re-submitted to server if the HTML is stored in the browser cache. | The browser usually alerts the user that data will need to be re-submitted. |
Encoding type (enctype attribute) | application/x-www-form-urlencoded | multipart/form-data or application/x-www-form-urlencoded Use multipart encoding for binary data. |
Parameters | can send but the parameter data is limited to what we can stuff into the request line (URL). Safest to use less than 2K of parameters, some servers handle up to 64K | Can send parameters, including uploading files, to the server. |
Hacked | Easier to hack for script kiddies | More difficult to hack |
Restrictions on form data type | Yes, only ASCII characters allowed. | No restrictions. Binary data is also allowed. |
Security | GET is less secure compared to POST because data sent is part of the URL. So it’s saved in browser history and server logs in plaintext. | POST is a little safer than GET because the parameters are not stored in browser history or in web server logs. |
Restrictions on form data length | Yes, since form data is in the URL and URL length is restricted. A safe URL length limit is often 2048 characters but varies by browser and web server. | No restrictions |
Usability | GET method should not be used when sending passwords or other sensitive information. | POST method used when sending passwords or other sensitive information. |
Visibility | GET method is visible to everyone (it will be displayed in the browser’s address bar) and has limits on the amount of information to send. | POST method variables are not displayed in the URL. |
Cached | Can be cached | Not cached |
So, basically we should know following points:
Simply put, GET requests are more useable; Use GET for safe actions and POST for unsafe actions. :
- GET requests can be cached
- GET requests can remain in the browser history
- GET requests can be bookmarked
- GET requests can be distributed & shared
- GET requests can be hacked
- Use POST when dealing with sensitive data.
- Use POST when dealing with long requests or sending larger data.
3) Materials needed
- NodeMcu ESP8266
- Computer / Raspberry Pi
4) Example 1: HTTP GET request with ESP8266
In this example the ESP8266 connects through WiFi to the internet and acts as a client sending HTTP GET requests to ESP8266-Shop.com. The URL is empty, which means no data is send along with the request URL. It’s basically the same request we send when we enter a web address in our browser. As response, the server sends the plain HTML in text format.
/* This sketch sends data via HTTP GET requests to esp8266-shop.com and returns the website in html format which is printed on the console */ #include <ESP8266WiFi.h> const char* ssid = "your-ssid"; //replace with your own wifi ssid const char* password = "your-password"; //replace with your own //wifi ssid password const char* host = "esp8266-shop.com"; void setup() { Serial.begin(115200); delay(10); // We start by connecting to a WiFi network Serial.println(); Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); /* Explicitly set the ESP8266 to be a WiFi-client, otherwise, it by default, would try to act as both a client and an access-point and could cause network-issues with your other WiFi-devices on your WiFi-network. */ WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } int value = 0; void loop() { delay(5000); ++value; Serial.print("connecting to "); Serial.println(host); // Use WiFiClient class to create TCP connections WiFiClient client; const int httpPort = 80; if (!client.connect(host, httpPort)) { Serial.println("connection failed"); return; } // We now create a URI for the request //this url contains the informtation we want to send to the server //if esp8266 only requests the website, the url is empty String url = "/"; /* url += "?param1="; url += param1; url += "?param2="; url += param2; */ Serial.print("Requesting URL: "); Serial.println(url); // This will send the request to the server client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); unsigned long timeout = millis(); while (client.available() == 0) { if (millis() - timeout > 5000) { Serial.println(">>> Client Timeout !"); client.stop(); return; } } // Read all the lines of the reply from server and print them to Serial while (client.available()) { String line = client.readStringUntil('\r'); Serial.print(line); } Serial.println(); Serial.println("closing connection"); }
5) Example 2: HTTP POST request with ESP8266
In this example the ESP8266 connects through WiFi to the internet and acts as a client sending HTTP POST requests to postman-echo.com that is a free service that echoes POST and GEt requests back to the sender. The URL is “/posts” without containing any data, but the payload contains the value of an ADC reading. Since the server in this case expects data in a POST request and will send the payload data back in a response message to the ESP8266.
#include <ESP8266WiFi.h> #include <ESP8266HTTPClient.h> const char* ssid = "YOUR SSID"; const char* password = "YOUR SSID PASSWORD"; const char* host = "postman-echo.com"; //edit the host adress, ip address etc. String url = "/post/"; int adcvalue=0; void setup() { Serial.begin(115200); delay(10); // We start by connecting to a WiFi network Serial.println(); Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); /* Explicitly set the ESP8266 to be a WiFi-client, otherwise, it by default, would try to act as both a client and an access-point and could cause network-issues with your other WiFi-devices on your WiFi-network. */ WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } int value = 0; void loop() { delay(5000); adcvalue=analogRead(A0); //Read Analog value of pin A0 Serial.print("connecting to "); Serial.println(host); // Use WiFiClient class to create TCP connections WiFiClient client; const int httpPort = 80; if (!client.connect(host, httpPort)) { Serial.println("connection failed"); return; } Serial.print("Requesting URL: "); Serial.println(url); //Post Data String postData = "adcreading=" + String(adcvalue); String address = host + url; HTTPClient http; http.begin(address); http.addHeader("Content-Type", "application/x-www-form-urlencoded"); auto httpCode = http.POST(postData); Serial.println(httpCode); //Print HTTP return code String payload = http.getString(); Serial.println(payload); //Print request response payload http.end(); //Close connection Serial.println(); Serial.println("closing connection"); }
6) Testing
Upload the code and open serial monitor, in case of any problem it will show errors. The ESP8266 will print the request and the response of the GET and POST requests.

7) Wrap-Up
As we have seen in both examples, it is quite easy to make GET and POST requests from the ESP8266. The only tricky part is to manipulate Strings in the URL or the payload (in case of the POST request).
We learned that simple requests that are shorter than 2000 characters and do not contain sensitive data such as passwords can be done via GET requests. Sensitive data and larger data must be send and received by POST requests.
Bear in mind that using a POST request alone does not make your communication secure. It just makes sure that sensitive data is not in in the request URL. Thus, we make sure that this data cannot be cached, or bookmarked. However, if a third party is able to catch the requests and responses, he will be able to read the full content.
In order to have a secure communication, the request needs to be encrypted via SSL/TLS (https vs. http), such that only sender and receiver are able to read the content of each message.
http.POST(postData) is not working 🙁
Can I send POST requests to multiple routes like
/tempData and /gpsData simultaneously ?
I tried your example 1 and I am getting the following error:
esptool v0.4.13-1-gf80ae31 – (c) 2014 Ch. Klippel
setting board to nodemcu
setting baudrate from 115200 to 115200
setting port from COM1 to COM3
An error occurred while uploading the sketch
setting address from 0x00000000 to 0x00000000
espcomm_upload_file
espcomm_upload_mem
setting serial port timeouts to 1000 ms
opening bootloader
resetting board
trying to connect
flush start
setting serial port timeouts to 1 ms
setting serial port timeouts to 1000 ms
flush complete
espcomm_send_command: sending command header
espcomm_send_command: sending command payload
serialport_receive_C0: 00 instead of C0
trying to connect
flush start
setting serial port timeouts to 1 ms
setting serial port timeouts to 1000 ms
flush complete
espcomm_send_command: sending command header
espcomm_send_command: sending command payload
read 0, requested 1
trying to connect
flush start
setting serial port timeouts to 1 ms
setting serial port timeouts to 1000 ms
flush complete
espcomm_send_command: sending command header
espcomm_send_command: sending command payload
read 0, requested 1
resetting board
trying to connect
flush start
setting serial port timeouts to 1 ms
setting serial port timeouts to 1000 ms
flush complete
espcomm_send_command: sending command header
espcomm_send_command: sending command payload
serialport_receive_C0: 00 instead of C0
trying to connect
flush start
setting serial port timeouts to 1 ms
setting serial port timeouts to 1000 ms
flush complete
espcomm_send_command: sending command header
espcomm_send_command: sending command payload
read 0, requested 1
trying to connect
flush start
setting serial port timeouts to 1 ms
setting serial port timeouts to 1000 ms
flush complete
espcomm_send_command: sending command header
espcomm_send_command: sending command payload
read 0, requested 1
resetting board
trying to connect
flush start
setting serial port timeouts to 1 ms
setting serial port timeouts to 1000 ms
flush complete
espcomm_send_command: sending command header
espcomm_send_command: sending command payload
serialport_receive_C0: 00 instead of C0
trying to connect
flush start
setting serial port timeouts to 1 ms
setting serial port timeouts to 1000 ms
flush complete
espcomm_send_command: sending command header
espcomm_send_command: sending command payload
read 0, requested 1
trying to connect
flush start
setting serial port timeouts to 1 ms
setting serial port timeouts to 1000 ms
flush complete
espcomm_send_command: sending command header
espcomm_send_command: sending command payload
read 0, requested 1
warning: espcomm_sync failed
error: espcomm_open failed
error: espcomm_upload_mem failed
Can you help me to solve this problem please?
Hi!
I’m testing both POST and GET methods, but I’m not sure how to address to my script on the server. In the POST mode I would think I should put:
String url = “/data/receive_temp.php”;
But I cant get this to work. I have tested the PHP script for both PUT and GET and this work fine on the web and I receive the data in my sql database.
Not sure of the date of this write up but seems some of the syntax has been depricated.
Arduino: 1.8.15 (Windows 7), Board: “Generic ESP8266 Module, 80 MHz, Flash, Disabled (new aborts on oom), Disabled, All SSL ciphers (most compatible), 32KB cache + 32KB IRAM (balanced), Use pgm_read macros for IRAM/PROGMEM, dtr (aka nodemcu), 26 MHz, 40MHz, DOUT (compatible), 1MB (FS:64KB OTA:~470KB), 2, nonos-sdk 2.2.1+100 (190703), v2 Lower Memory, Disabled, None, Only Sketch, 115200”
C:\Users\Video\Documents\Arduino\sensor_test\sensor_test.ino: In function ‘void loop()’:
sensor_test:45:11: error: call to ‘HTTPClient::begin’ declared with attribute error: obsolete API, use ::begin(WiFiClient, url)
45 | http.begin(address);
| ~~~~~~~~~~^~~~~~~~~
exit status 1
call to ‘HTTPClient::begin’ declared with attribute error: obsolete API, use ::begin(WiFiClient, url)
This report would have more information with
“Show verbose output during compilation”
option enabled in File -> Preferences.
this is all i get from the code
WiFi connected
IP address:
192.168.0.116
connecting to https://esp8266-shop.com/
connection failed
so i tried the simple google.com
with the same outcome