Skip to content

Get the time from the internet on ESP32, ESP8266 and Arduino with a time API

ESP32 and Arduino sketches that get the local time over HTTPS with the time zone and DST applied: set the clock, parse JSON or .txt, and when to use NTP.

Updated

Short answer: an ESP32, ESP8266 or Arduino with Wi-Fi can get the current local time from the internet with one HTTPS request. The response already has the time zone offset and daylight saving applied, which NTP does not give you.

// GET https://api.timelogicapi.com/api/timezone/America/New_York?api_key=YOUR_KEY
// -> {"utc_offset":"-04:00","timezone":"America/New_York","datetime":"...","unixtime":...,"dst":true, ...}

NTP or a time API: which should my sketch use?

FeatureNTP (configTime)HTTPS time API
Gives youUTC timeLocal time, UTC time, offset, DST flag and dates, ISO week
Time zones and DSTYou write a POSIX TZ string and keep it currentApplied by the API from the IANA tz database
NetworkUDP port 123HTTPS port 443
Find the zone automaticallyNoYes, from the device's public IP (/api/ip)
KeyNoneAPI key (Free plan: 10,000 requests per month)

Many projects use both: NTP to keep the clock ticking, and one API call at boot (or once a day) to learn the zone and offset. More detail in NTP vs a time API.

ESP32: get the local time and set the clock

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <sys/time.h>

const char* WIFI_SSID = "your-ssid";
const char* WIFI_PASS = "your-password";
const char* API_KEY   = "YOUR_KEY";

bool syncTime() {
  WiFiClientSecure client;
  client.setInsecure();  // quick start; use client.setCACert(rootCA) in production
  HTTPClient http;
  http.begin(client, "https://api.timelogicapi.com/api/timezone/America/New_York");
  http.addHeader("X-API-Key", API_KEY);
  int code = http.GET();
  if (code != 200) { Serial.printf("HTTP %d\n", code); http.end(); return false; }

  JsonDocument doc;  // ArduinoJson 7
  DeserializationError err = deserializeJson(doc, http.getString());
  http.end();
  if (err) return false;

  struct timeval tv;
  tv.tv_sec = (time_t)doc["unixtime"].as<long>();
  tv.tv_usec = 0;
  settimeofday(&tv, nullptr);  // system clock now holds UTC
  Serial.println(doc["datetime"].as<const char*>());  // local time with offset
  Serial.println(doc["dst"].as<bool>() ? "DST in effect" : "standard time");
  return true;
}

void setup() {
  Serial.begin(115200);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) delay(250);
  syncTime();
}

void loop() {
  time_t now = time(nullptr);  // keeps counting after the sync
  Serial.println((long)now);
  delay(10000);
}

To use the device's own location instead of a fixed zone, request /api/ip instead of /api/timezone/America/New_York; the zone is resolved from the public IP address the request comes from.

ESP8266

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

void printTime() {
  std::unique_ptr<BearSSL::WiFiClientSecure> client(new BearSSL::WiFiClientSecure);
  client->setInsecure();  // quick start; pin a certificate for production
  HTTPClient https;
  https.begin(*client, "https://api.timelogicapi.com/api/timezone/Europe/Berlin.txt?api_key=YOUR_KEY");
  if (https.GET() == 200) Serial.println(https.getString());
  https.end();
}

Parse the .txt response without a JSON library

String body = http.getString();               // from a .txt URL
int i = body.indexOf("unixtime: ");
long unixtime = body.substring(i + 10, body.indexOf('\n', i)).toInt();

The .txt form lists the same 15 fields as key: value lines in alphabetical order, so unixtime: is always present.

Which fields does the response carry?

datetime (local, with offset), utc_datetime, unixtime, utc_offset, raw_offset and dst_offset (seconds), dst, dst_from, dst_until, abbreviation, timezone, day_of_week (0 = Sunday), day_of_year, week_number (ISO) and client_ip. Full table: WorldTimeAPI-compatible routes.

Prefer the /v1 API? GET /v1/time/current?tz=America/New_York returns unix, unix_ms, iso_local and the weekday names; see the current time reference.

Tips for devices

  • Sync, don't poll. One request at boot and one every few hours is plenty; the RTC keeps time in between. 10,000 free requests a month is roughly one request every 4 to 5 minutes from a single device.
  • Keep the key out of public repos. Put it in a secrets.h that is not committed.
  • Handle failures. If the request fails, keep running on the last synced time and retry later.

Related guides

Frequently asked questions

How do I get the time from the internet on an ESP32?

Two ways. NTP with configTime() sets the clock in UTC and you supply the time zone rules yourself. An HTTPS time API returns the local time, the UTC offset and the DST state in one request: GET https://api.timelogicapi.com/api/timezone/Europe/London?api_key=YOUR_KEY returns datetime, unixtime, utc_offset and dst.

Can an ESP32 get the time without NTP?

Yes. Fetch the time over HTTPS from a time API, read unixtime, and set the system clock with settimeofday(). This also works on networks that block NTP's UDP port 123 but allow HTTPS.

How do I handle daylight saving time on an Arduino?

Let the API do it. The response for a zone such as America/New_York already includes the current offset (utc_offset, raw_offset, dst_offset) and whether DST is in effect, so the sketch does not need a POSIX TZ string or its own DST table.

Why does my old worldtimeapi.org sketch fail?

worldtimeapi.org was shut down in 2026. Point the sketch at https://api.timelogicapi.com with the same path and add your API key; the JSON fields are the same.

Do I need ArduinoJson?

No. Add .txt to the path and the response is plain key: value lines, so you can find the unixtime: line with String functions.