How to serve /favicon.ico without using a flash to save the image

I have a webserver setup on my arduino and i would like to cater to the favicon.ico requested by most browsers. Problem is i do not have a storage device conneccted to the mCU nor i do not want to set up a software storage.

Is it possible to return to the a browser a string format of the image?

How would the headers of my http response look like? and what format should i use to convert the image to a string?

what do you mean by "without using a flash to save the image"

You need to store the answer somewhere. whether it's in flash like PROGMEM or littleFS (assuming an ESP type of Arduino) or sram it will eat up memory.

if you can host your picture somewhere on the internet you could probably redirect there too if you want very limited memory impact (never tried)

I would like it to be saved inside a variable in my sketch as either a bianry data, or some other form of maybe a long string.

I was thinking of converting the image to some sort of a string format, save it on a variable in a separate .h file inisde the source code. When a client request it , return it to the client by

      String imageString = // some long string equivalent of the image

      client.println("HTTP/1.1 200 OK");
      client.println("Content-Type: text/html");
      client.println("Connection: close");  
      client.println();
      client.println(imageString);
      client.stop();

Something like the code above.

i have read in this thread that you can encode it in base64. But i do not if the browsers accept that and if they do, how would i set up my http headers

are you on an ESP32 ?
I assume you are not using ESPAsyncWebServer given the code

No , i am not using ESP32

I am using a rp2040 board with a w5500 ethernet module

so you've plenty of flash storage. have you tried using littleFS (LittleFS_Mbed_RP2040 - Arduino Reference) to just store the file and serve the file?

you can use this link HERE to encode your image (png,jpeg,etc) into a base64

you will end up with a long string like this 'data:image/jpeg;base64,/....'

I suggest you reduce your image resolution size so as to have shorter string ( hence less bytes consumed when deployed in your code )

then back to your code which would look something like this


           String imageString = "data:image/jpeg;base64,/....";

           client.println("HTTP/1.1 200 OK"); //send new page
           client.println("Content-Type: text/html");
           client.println();     
           client.println("<HTML>");
           client.println("<HEAD>");
           client.println("<meta name='apple-mobile-web-app-capable' content='yes' />");
           client.println("<meta name='apple-mobile-web-app-status-bar-style' content='black-translucent' />");
           client.println("<link  rel='shortcut icon' type='image/png' href=\"");
           client.println(imageString);
           client.println("\">");
           client.println("<TITLE> some web title </TITLE>");

more from HERE

Okay there is some problems i would seem that client.println / char / string has a max character count of exactly 2047 (11bits). So i had to split it into several strings.

Is this supposed to be the reply of the the main " GET /" request or the reply of "GET /favicon.ico" request?

I tried this on the "GET /favicon.ico" and the icon does show on the link ''http://192.168.1.8/favicon.ico'' but the icon does not show on the main ''http://192.168.1.8"

I kinda dont want to setup littleFS just for this one file. Since its not that much of a priority. Hence me trying to look for alternatives first before resorting to using that. And KASSIMSAMJI seems to have a solution.

I dug up an old test code that I had written for Arduino Uno and an Ethernet shield

the goal was to serve this image as an favicon
favicon
(Here in png but I used the .ico version)

There is nothing really rocket science about it, you don't need to stuff your memory with a base64 answer. a byte stream is good enough - just as if you were serving the file from disk.

Here is the code:

this is the main .ino file

#include <Ethernet.h>
#include "html.h"

EthernetServer webServer(80);
byte serverMacAddress[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xF0, 0x0D};
IPAddress serverIPAddress(10, 0, 0, 29);

void dumpBuffer(const uint8_t * ptr, const size_t n) {
  for (size_t i = 0; i < n; i++) {
    uint8_t b = *(ptr + i);
    if (b < 0x10) Serial.write('0');
    Serial.print(b, HEX);
    if ((i + 1) % 16 == 0) Serial.println(); else Serial.write(' ');
  }
  Serial.println();
}

void dealWithRequest(const char * httpRequest, EthernetClient& client) {
  Serial.print(F("Handing Request : [")); Serial.print(httpRequest); Serial.println(F("]"));

  if (strncmp(httpRequest + 4, "/ ", 2) == 0) {             // first 4 chars are assumed to be "GET "
    client.print((const __FlashStringHelper*) httpHeader);
    client.print((const __FlashStringHelper*) homePage);
  }
  else if (strncmp(httpRequest + 4, "/favicon", 8) == 0) {  // first 4 chars are assumed to be "GET "
    Serial.println("Favicon request");
    client.print((const __FlashStringHelper*) favIconHeader);  // don't use println() or you'll add extra CRLF into the binary stream
    const byte bufferSize = 48;
    uint8_t buffer[bufferSize];
    const size_t n = sizeof favicon / bufferSize;
    const size_t r = sizeof favicon % bufferSize;
    for (size_t i = 0; i < sizeof favicon; i += bufferSize) {
      memcpy_P(buffer, favicon + i, bufferSize);
      // dumpBuffer(buffer, bufferSize);
      client.write(buffer, bufferSize);
    }
    if (r != 0) {
      memcpy_P(buffer, favicon + n * bufferSize, r);
      // dumpBuffer(buffer, r);
      client.write(buffer, r);
    }
  }
  else client.print((const __FlashStringHelper*) errorHeader);
}

void setup() {
  Serial.begin(115200);
  while (!Serial) yield();
  Serial.println();
  Ethernet.begin(serverMacAddress, serverIPAddress);

  webServer.begin();
  Serial.print("Reach your server at http://"); Serial.println(Ethernet.localIP());
}

void loop() {
  EthernetClient client;
  const size_t urlMaxSize = 30;
  char httpRequest[urlMaxSize + 1];
  unsigned int httpRequestIndex;
  boolean gotGET, lineIsEmpty;

  client = webServer.available();
  if (client) {
    httpRequestIndex = 0;
    httpRequest[0] = '\0';
    gotGET = false;
    lineIsEmpty = true;

    while (client.connected()) {
      if (client.available()) {
        char incomingByte = client.read();
        if (incomingByte != '\r') {
          if (incomingByte != '\n') {
            lineIsEmpty = false;
            if (!gotGET) {
              httpRequest[httpRequestIndex++] = incomingByte;
              httpRequest[httpRequestIndex] = '\0';
              if (httpRequestIndex >= urlMaxSize) httpRequestIndex = urlMaxSize - 1;
            }
          } else {
            if (lineIsEmpty) break;
            else {
              lineIsEmpty = true;
              gotGET = strncmp(httpRequest, "GET", 3) == 0;
              if (!gotGET) {
                httpRequest[0] = '\0';
                httpRequestIndex = 0;
              }
            }
          }
        }
      }
    }
    dealWithRequest(httpRequest, client);
    delay(1);
    client.stop();
  }
}

this is a side file that you need to have in the same directory as your sketch. file name needs to match the #include "html.h" in the .ino file

html.h

#ifndef _HTML_
#define _HTML_

const char httpHeader[] PROGMEM = R"--(HTTP/1.1 200 OK
Content-Type: text/html
Connection: close

)--";

const char errorHeader[] PROGMEM = R"--(HTTP/1.1 404 Not Found
Connection: close

)--";

const char favIconHeader[] PROGMEM = R"--(HTTP/1.1 200 OK
Content-Type: image/ico
Connection: close

)--";
                 
const char homePage[] PROGMEM = R"--(
<!DOCTYPE html>
<html>
  <head><title>FAVICON DEMO</title></head>
  <body>Hello World</body>
</html>
)--";

// generated array content with "xxd -c16 --include favicon.ico" (unix command line)
const uint8_t favicon[] PROGMEM = {
  0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x10, 0x10, 0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x68, 0x04,
  0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x20, 0x00,
  0x00, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  0xbc, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xbc, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  0xbc, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xbc, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  0xbc, 0xff, 0xff, 0x00, 0xbc, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  0xbc, 0xff, 0xff, 0x00, 0xbc, 0xff, 0xff, 0x00, 0xbc, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  0xbc, 0xff, 0xff, 0x00, 0xbc, 0xff, 0xff, 0x00, 0xbc, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  0xbc, 0xff, 0xff, 0x00, 0xbc, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  0xbc, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xbc, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  0xbc, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xbc, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  0xbc, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xbc, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  0xbc, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xbc, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  0xbc, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xbc, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  0xbc, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xbc, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0xff, 0x00, 0xbc, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  0xbc, 0xff, 0xff, 0x00, 0xbc, 0xff, 0xff, 0x00, 0xbc, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  0xbc, 0xff, 0xff, 0x00, 0xbc, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
  0xbc, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xbc, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x09, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x09, 0xff,
  0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x09, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x09, 0xff,
  0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x09, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x09, 0xff,
  0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x09, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x09, 0xff, 0x00, 0xff, 0x00, 0x00,
  0xff, 0xff, 0x09, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x09, 0xff, 0x00, 0xff, 0x00, 0x00,
  0xff, 0xff, 0x09, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x09, 0xff, 0x00, 0xff, 0x00, 0x00,
  0xff, 0xff, 0x09, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b,
  0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x09, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b, 0x00, 0xff, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b,
  0x00, 0xff, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b, 0x00, 0xff, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b,
  0x00, 0xff, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b, 0x00, 0xff, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b, 0x00, 0xff, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b, 0x00, 0xff, 0xff, 0x2b,
  0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x09, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x31,
  0x00, 0x00, 0x13, 0x55, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0xb1, 0x35, 0x00, 0x00, 0xff, 0xff,
  0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x99, 0x85,
  0x00, 0x00, 0x99, 0xcf, 0x00, 0x00, 0x81, 0xcd, 0x00, 0x00, 0x81, 0xcd, 0x00, 0x00, 0x99, 0xcd,
  0x00, 0x00, 0x99, 0x85, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00
};

#endif

you can see in this second file the byte array const uint8_t favicon[] that I filled up with an hex dump of my .ico file, which I obtained thanks to the unix command line:
xxd -c16 --include favicon.ico

You can draw an icon using an online tool here: http://onlinefavicon.com

give it a try (you might need to adjust the PROGMEM stuff and the memcpy_P() in the main code that is for AVR - I don't know if they have a compatibility layer for the rp2040.

I tried the code and it does still work with Chrome or Safari

chrome

➜ what you need to send to the client when you identify the request is a header with an empty line at the end

HTTP/1.1 200 OK
Content-Type: image/ico
Connection: close

and then the byte stream for the image

PS/ of course this needs to be adjusted to suit your needs

byte serverMacAddress[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xF0, 0x0D};
IPAddress serverIPAddress(10, 0, 0, 29);

have you tried to change

type='image/png'

to

type='image/ico'

Jackson has a point too, this string solution really stuff up the memory,

you could change the ico to png/jpeg and start the procedure all over,

I hope you did remember enclosing the header with a < /header >

and by having ''http://192.168.1.8/favicon.ico'' means all is well, clicking that hyper-link browser should take you to a new tab with the image displaying

So here is the full function that handles favicon

if (x->httpPath == "/favicon.ico") {
  client.println("HTTP/1.1 200 OK"); //send new page
  client.println("Content-Type: text/html");
  client.println();
  client.println("<HTML>");
  client.println("<HEAD>");
  client.println("<meta charset=\"utf-8\"/>");
  client.println("<meta name='apple-mobile-web-app-capable' content='yes' />");
  client.println("<meta name='apple-mobile-web-app-status-bar-style' content='black-translucent' />");
  client.print("<link  rel='shortcut icon' type='image/ico' href=\"");

  client.print(htmlIcon1);
  client.print(htmlIcon2);
  client.print(htmlIcon3);
  client.print(htmlIcon4);
  client.print(htmlIcon5);
  client.print(htmlIcon6);
  client.print(htmlIcon7);
  client.print(htmlIcon8);
  client.print(htmlIcon9);
  client.print(htmlIcon10);
  client.print(htmlIcon11);

  client.println("\">");
  client.println("</HEAD>");
  client.println("</HTML>");
  client.stop();
}

That is indeed what is happening ,

but in the main html( http://192.168.1.8) does not have the icon.

if i include the in the main html the browsers does not ask for favicon anymore as the html already has it. I am just trying to add icing on the cake by optimizing. 100ms is added to load the main html if i include the icon there. If i am able to send to http://192.168.1.8/favicon.ico the icon, the browser will cache the icon so the next time the main html is loaded the it will be 100ms faster and the mcu can do some other task.

Add the following html the <head> section of your website

<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />

then the browser should use that link an cache it

have you tried the code I posted above?

The icon is still not showing up on the main html.

    if (x->httpPath == "/") {
      client.println("HTTP/1.1 200 OK");
      client.println("Content-Type: text/html");
      client.println("Connection: close");
      client.println();

      client.println("<!DOCTYPE HTML>");
      client.println("<HEAD>");
      client.println("<link rel=\"shortcut icon\" href=\"/favicon.ico\" type=\"image/x-icon\" />");
      client.println("</HEAD>");

      client.println(htmlString);
      client.stop();
      return;
    }

    if (x->httpPath == "/favicon.ico") {
      client.println("HTTP/1.1 200 OK"); //send new page
      client.println("Content-Type: text/html");
      client.println("Connection: close");

      client.println();
      client.println("<HTML>");
      client.println("<HEAD>");
      client.println("<meta charset=\"utf-8\"/>");
      client.println("<meta name='apple-mobile-web-app-capable' content='yes' />");
      client.println("<meta name='apple-mobile-web-app-status-bar-style' content='black-translucent' />");
      client.print("<link  rel='shortcut icon' type='image/ico' href=\"");

      client.print(htmlIcon1);
      client.print(htmlIcon2);
      client.print(htmlIcon3);
      client.print(htmlIcon4);
      client.print(htmlIcon5);
      client.print(htmlIcon6);
      client.print(htmlIcon7);
      client.print(htmlIcon8);
      client.print(htmlIcon9);
      client.print(htmlIcon10);
      client.print(htmlIcon11);

      client.println("\">");
      client.println("</HEAD>");
      client.println("</HTML>");
      client.stop();
    }

I can make it so that the icon show up on the main html but the problem is each request will always take 200ms to finish,

    if (x->httpPath == "/") {
      client.println("HTTP/1.1 200 OK");
      client.println("Content-Type: text/html");
      client.println("Connection: close");
      client.println();

      client.println("<!DOCTYPE HTML>");
      client.println("<HEAD>");
      client.println("<meta charset=\"utf-8\"/>");
      client.println("<meta name='apple-mobile-web-app-capable' content='yes' />");
      client.println("<meta name='apple-mobile-web-app-status-bar-style' content='black-translucent' />");
      client.print("<link  rel='shortcut icon' type='image/png' href=\"");
      client.print(htmlIcon1);
      client.print(htmlIcon2);
      client.print(htmlIcon3);
      client.print(htmlIcon4);
      client.print(htmlIcon5);
      client.print(htmlIcon6);
      client.print(htmlIcon7);
      client.print(htmlIcon8);
      client.print(htmlIcon9);
      client.print(htmlIcon10);
      client.print(htmlIcon11);
      client.println("\">");
      client.println("</HEAD>");

      client.println(htmlString);
      client.stop();
      return;
    }

The only thing i dont like with this as i mentioned in previous post each request will take 130ms (lower right of the image shows the time) compared to a cached favico which is 70ms

I'm not sure what I'm looking at

I see a blue circle as a favicon and I see one downloaded and then one cached

there is two images in that one, the first one ( upper part) is when the bowser intially requests to the server which of course requests for '/' and 'favicon.ico'. The second images ( The one below) is after the page is refreshed. The browser (mozzila in this case) does not request for the favicon anymore because it already has one in cache

I have no problem showing the icon in the '/favicon.ico' request. My problem is the main html (with the header 'Title of the document') does not contain the icon. If i understand correctly the browser will request for a '/favicon.ico' when '/' does not contain a header icon. Since have responded to '/favicon.ico' with an image i am expecting an icon on the main html. Something like this.

image

let me get that right : you want to see the image as part of the body of html page?

then it's an image request you need to have in the body of the document
<img src="favicon.ico" alt="this is the favicon">
they might be managed and cached separately by the browser.

let me try this one by "this is the favicon" you mean this right?

`<img src="favicon.ico" alt="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGQAAAB0CAYA . . . . ">`

no I meant literally having that in the body of the page, The browser will see a need for downloading an image and will issue a request for the /favicon.ico image and then will paint it in the page.

the icon used in the tab is a special request that has nothing to do with the content of your web page.

The server sees just a request for an image (hence my code example where you blast the bits out). What the browser does with the image depends on why the call was made; if that request was from the browser to add some fun to the tab, then it will handle the image for that. If the request was part of a web page, then it gets displayed.

This ! i want the png image to be used in the tab.

i have responsded to this special request and the icon on the tab is not showing up

the special request you are refering to is the '/favicon.ico' request i have been talking about in the previous posts.

lets go back from the start... This special request you are refering to, how should i respond to it? (not ignoring it but by sending an icon)