Bonnie Eisenman bio photo

Bonnie Eisenman

Software engineer, author, knitter, Esperantist. Member of NYC Resistor and author of Learning React Native.

🐦 Twitter 🤖 Github 🔶 RSS Feed

Last week I taught a DIY Internet of Things class at NYC Resistor. We used the Adafruit Feather HUZZAH board, which has an ESP8266 WiFi chip. I hadn’t worked with this chip before. Turns out, it’s pretty great!

I also grabbed an OLED FeatherWing. Possibly the cutest screen I’ve ever worked with. OMG so tiny.

Anyway, once I had it all assembled the first step was to test out the WiFi. Adafruit provides some example code. Here’s the code, abbreviated:

const char* ssid     = "yourssid";
const char* password = "yourpassword";

const char* host = "";
String url = "/testwifi/index.html";

void setup() {
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {

void loop() {
    // Use WiFiClient class to create TCP connections
    WiFiClient client;
    const int httpPort = 80;
    if (!client.connect(host, httpPort)) {

    client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "Connection: close\r\n\r\n");

        String line = client.readStringUntil('\r');


This is a much lower-level API than I expected! I really did not anticipate having to hand-craft artisinal HTTP messages.

For the class project, I wanted students to build an alarm clock, using a web API to fetch the current time. provides a super-duper-simple API that does just that.

$ curl

However, at first, when I tried sending a GET request from the Feather to the above URL, it…didn’t work. I got a 403 Rejected.

Hmm. That’s odd. I took another look at the request I was sending:

> GET /est/now HTTP/1.1
> Host:

I double-checked it against curl:

$ curl -v
*   Trying
* Connected to ( port 80 (#0)
> GET /est/now HTTP/1.1
> Host:
> User-Agent: curl/7.43.0
> Accept: */*

There are only two lines that differ:

> User-Agent: curl/7.43.0
> Accept: */*

Oh, derp. The example code doesn’t include a User-Agent string. This is fine for the wifitest page that Adafruit has set up, but won’t work for most actual sites.

So, I just modified the sketch to send the User-Agent as curl/7.43.0. Because User-Agent strings are nonsense anyway, right? And laziness is a virtue, etc, etc…

client.println(String("GET ") + url + " HTTP/1.1");
client.print("Host: ");
client.println("User-Agent: curl/7.43.0");

Lo and behold, now it works.

That was really the main hurdle - otherwise, working with the Feather HUZZAH was surprisingly easy. Now I need to actually finish a project with it. ;)

The full sketch, along with other code samples from the class, is available on github.