Categories
Arduino Hardware Programming Tutorial

Accessing Virtual Hosts with Arduino Ethernet Shield

If you've worked with the Arduino Ethernet Shield, you've probably noticed a limitation: while you can connect to an IP address, you can only reach the default virtual host on that server. This becomes a problem when working with shared hosting or VPS servers that host multiple websites on a single IP address.

The Problem

Modern web servers commonly use virtual hosting to serve multiple websites from a single IP address. When you make a basic HTTP request to an IP, the server returns the default site—not necessarily the one you want. On commercial shared hosting, you typically can't make your site the default host.

The Solution: HTTP Host Header

The key is using the HTTP protocol properly. HTTP allows you to specify which virtual host you want to access by including a Host header in your request. This tells the server exactly which website you're trying to reach, even when multiple sites share the same IP address.

Complete Arduino Code

Here's a working example that demonstrates how to access a specific virtual host:

#include <SPI.h>
#include <Ethernet.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 6, 30 };

// Replace with your server's IP address
byte server[] = { 192, 168, 168, 16 }; // Your VPS

// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
Client client(server, 80);

String response = "";
boolean reset = false;

void setup() {
  Ethernet.begin(mac, ip);
  Serial.begin(9600);

  // Give the Ethernet shield a second to initialize
  delay(1000);
  Serial.println("Connecting...");
}

void loop() {
  // If not connected, try to connect
  if (!client.available() && !client.connected() && client.connect()) {
    Serial.println("-- Connected");

    // Make a HTTP request with proper headers
    client.println("GET /bot HTTP/1.0");
    client.println("Host: example.com");  // Specify the virtual host
    client.println("User-Agent: Arduino/1.0");
    client.println();  // Empty line to end headers

    reset = false;
  }

  // Read available data
  if (client.available()) {
    char c = client.read();
    response.concat(c);
  }

  // Process response when connection closes
  if (!client.connected() && response.length() > 0) {
    process(response);
    reset = true;
  }

  // Cleanup and wait before next request
  if (!client.connected() && reset) {
    Serial.println("Disconnecting.");
    client.stop();
    response = "";
    delay(10000);  // Wait 10 seconds before next request
  }
}

void process(String response) {
  Serial.println("--- Response ---");
  Serial.println(response);
  Serial.println("----------------");
}

How It Works

MAC and IP Configuration:

byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 6, 30 };

Configure your Arduino's network identity. The MAC address should be unique on your network, and the IP should match your local network configuration.

Server Connection:

byte server[] = { 192, 168, 168, 16 };
Client client(server, 80);

Specify the server's IP address and port (80 for HTTP).

The Critical Part – HTTP Headers:

client.println("GET /bot HTTP/1.0");
client.println("Host: example.com");  // This is the key!
client.println("User-Agent: Arduino/1.0");
client.println();  // Empty line ends headers

The Host: example.com header is what makes this work. Replace example.com with your actual domain name. This tells the server which virtual host you want to access.

HTTP Headers You Should Include:

  1. Host (Required): The domain name you're trying to reach
  2. User-Agent (Recommended): Identifies your client for debugging and server logs
  3. Connection (Optional): Use Connection: close to have the server close the connection after responding

For a complete list of HTTP headers, see the HTTP headers Wikipedia page.

Testing Your Setup

  1. Upload the sketch to your Arduino
  2. Open the Serial Monitor (9600 baud)
  3. You should see: – "Connecting…" – "– Connected" – The HTTP response from your server – "Disconnecting."

If it's not working, check:

  • Your network configuration (MAC and IP addresses)
  • Server IP address is correct
  • The domain name in the Host header matches your virtual host
  • Your server is accessible from your network

Use Cases

This technique is useful for:

  • Accessing APIs hosted on shared servers
  • Monitoring specific websites on a VPS
  • IoT devices communicating with web services on virtual hosts
  • Arduino-based web scrapers or data collectors

Notes

HTTP/1.0 vs HTTP/1.1: This example uses HTTP/1.0 for simplicity. HTTP/1.1 requires the Host header and is generally preferred, but HTTP/1.0 works fine for basic requests.

Memory Considerations: The response string can grow large. For production use, consider processing data as it arrives rather than storing the entire response in memory.

Security: This example uses plain HTTP. For production systems, consider using HTTPS if your Arduino hardware and library support it.

View the original code on Gist.

By Shishir Sharma

Shishir Sharma is a Software Engineering Leader, husband, and father based in Ottawa, Canada. A hacker and biker at heart, and has built a career as a visionary mentor and relentless problem solver.

With a leadership pedigree that includes LinkedIn, Shopify, and Zoom, Shishir excels at scaling high-impact teams and systems. He possesses a native-level mastery of JavaScript, Ruby, Python, PHP, and C/C++, moving seamlessly between modern web stacks and low-level architecture.

A dedicated member of the tech community, he serves as a moderator at LUG-Jaipur. When he’s not leading engineering teams or exploring new technologies, you’ll find him on the open road on his bike, catching an action movie, or immersed in high-stakes FPS games.

2 replies on “Accessing Virtual Hosts with Arduino Ethernet Shield”

Leave a Reply to Shishir Sharma 'criss' Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.