- Home
- HTTP Headers
- Date Header
Header
Date Header
Learn how the Date header specifies when the HTTP message was originated by the server. Understand date formats and its role in caching and logging.
TL;DR: Timestamp showing when the HTTP response was generated by the server. Required in all responses and used for cache freshness calculations and debugging.
What is Date?
The Date header contains the date and time at which the HTTP message was originated. It’s like a timestamp saying “This response was created at exactly this moment.”
This header is required in all HTTP responses and is used for caching calculations, age determination, and synchronization purposes.
How Date Works
Server sends response with Date:
HTTP/1.1 200 OK
Date: Sat, 18 Jan 2026 10:30:00 GMT
Content-Type: application/json
Cache-Control: max-age=3600
{"message": "Hello World"}
```text
The Date header tells the client when the response was generated, which helps with cache freshness calculations.
## Syntax
```http
Date: <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT
Format
The Date header uses HTTP-date format (IMF-fixdate):
- Day name: Mon, Tue, Wed, Thu, Fri, Sat, Sun
- Month: Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec
- Always in GMT/UTC timezone
Common Examples
Standard Response
Date: Sat, 18 Jan 2026 10:30:00 GMT
```http
Response generated on January 18, 2026 at 10:30 AM GMT.
### With Caching
```http
Date: Sat, 18 Jan 2026 10:30:00 GMT
Cache-Control: max-age=3600
Age: 300
Response is 5 minutes old (Age), expires 1 hour after Date.
API Response
Date: Sat, 18 Jan 2026 14:25:30 GMT
Content-Type: application/json
X-RateLimit-Reset: 1737207930
```text
Date header helps correlate with rate limit reset time.
## Real-World Scenarios
### Cache Freshness Calculation
```http
GET /api/data HTTP/1.1
Host: api.example.com
HTTP/1.1 200 OK
Date: Sat, 18 Jan 2026 10:00:00 GMT
Cache-Control: max-age=600
Age: 120
{"data": "cached content"}
# Freshness calculation:
# Response age: 120 seconds (Age header)
# Max age: 600 seconds (Cache-Control)
# Remaining fresh: 480 seconds (600 - 120)
Conditional Requests
# Initial request
GET /resource HTTP/1.1
HTTP/1.1 200 OK
Date: Sat, 18 Jan 2026 10:00:00 GMT
Last-Modified: Sat, 18 Jan 2026 09:00:00 GMT
ETag: "abc123"
# Subsequent request
GET /resource HTTP/1.1
If-Modified-Since: Sat, 18 Jan 2026 09:00:00 GMT
HTTP/1.1 304 Not Modified
Date: Sat, 18 Jan 2026 10:05:00 GMT
```http
### API Rate Limiting
```http
GET /api/endpoint HTTP/1.1
HTTP/1.1 200 OK
Date: Sat, 18 Jan 2026 12:00:00 GMT
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 950
X-RateLimit-Reset: Sat, 18 Jan 2026 13:00:00 GMT
Time-Sensitive Operations
POST /api/transactions HTTP/1.1
HTTP/1.1 201 Created
Date: Sat, 18 Jan 2026 15:30:45 GMT
Content-Type: application/json
{
"id": "txn_123",
"timestamp": "2026-01-18T15:30:45Z",
"serverTime": "2026-01-18T15:30:45Z"
}
```javascript
## Server Implementation
### Express.js (Node.js)
```javascript
const express = require('express')
const app = express()
// Express automatically sets Date header, but you can set it manually
app.use((req, res, next) => {
// Custom Date header (rarely needed)
res.setHeader('Date', new Date().toUTCString())
next()
})
app.get('/api/data', (req, res) => {
// Date is automatically set
res.json({ data: 'example' })
})
// Calculate response age
app.get('/cached', (req, res) => {
const cacheDate = new Date('2026-01-18T10:00:00Z')
const now = new Date()
const age = Math.floor((now - cacheDate) / 1000)
res.setHeader('Date', now.toUTCString())
res.setHeader('Age', age.toString())
res.setHeader('Cache-Control', 'max-age=3600')
res.json({ cached: true })
})
// Check clock skew
app.use((req, res, next) => {
const clientDate = req.headers.date
if (clientDate) {
const clientTime = new Date(clientDate).getTime()
const serverTime = Date.now()
const skew = Math.abs(serverTime - clientTime) / 1000
if (skew > 300) {
// 5 minutes
console.warn(`Clock skew detected: ${skew} seconds`)
}
}
next()
})
Custom Date Formatting
function formatHTTPDate(date) {
const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
const months = [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec'
]
const day = days[date.getUTCDay()]
const dateNum = String(date.getUTCDate()).padStart(2, '0')
const month = months[date.getUTCMonth()]
const year = date.getUTCFullYear()
const hour = String(date.getUTCHours()).padStart(2, '0')
const minute = String(date.getUTCMinutes()).padStart(2, '0')
const second = String(date.getUTCSeconds()).padStart(2, '0')
return `${day}, ${dateNum} ${month} ${year} ${hour}:${minute}:${second} GMT`
}
app.use((req, res, next) => {
res.setHeader('Date', formatHTTPDate(new Date()))
next()
})
```javascript
### FastAPI (Python)
```python
from fastapi import FastAPI, Response
from datetime import datetime
from email.utils import formatdate
import time
app = FastAPI()
@app.middleware("http")
async def add_date_header(request, call_next):
response = await call_next(request)
# FastAPI sets Date automatically, but you can override
response.headers["Date"] = formatdate(timeval=None, localtime=False, usegmt=True)
return response
@app.get("/api/data")
async def get_data(response: Response):
# Date is automatically set
return {"data": "example"}
@app.get("/cached")
async def cached_response(response: Response):
# Calculate age
cache_time = datetime(2026, 1, 18, 10, 0, 0)
now = datetime.utcnow()
age = int((now - cache_time).total_seconds())
response.headers["Date"] = formatdate(timeval=None, localtime=False, usegmt=True)
response.headers["Age"] = str(age)
response.headers["Cache-Control"] = "max-age=3600"
return {"cached": True}
Django
from django.http import JsonResponse
from django.utils.http import http_date
import time
def api_view(request):
# Django automatically sets Date header
return JsonResponse({'data': 'example'})
def custom_date_view(request):
response = JsonResponse({'data': 'example'})
# Set custom Date (rarely needed)
response['Date'] = http_date()
return response
def cached_view(request):
# Calculate age
cache_timestamp = 1737198000 # Unix timestamp
now = time.time()
age = int(now - cache_timestamp)
response = JsonResponse({'cached': True})
response['Date'] = http_date()
response['Age'] = str(age)
response['Cache-Control'] = 'max-age=3600'
return response
```nginx
### Nginx
```nginx
server {
listen 80;
server_name example.com;
# Nginx automatically adds Date header
location /api/ {
# Date is always added by default
proxy_pass http://backend;
}
# You can't easily override Date in Nginx
# It's automatically set to the current time
}
Best Practices
For Servers
1. Always include Date header
# ✅ Required in all responses
HTTP/1.1 200 OK
Date: Sat, 18 Jan 2026 10:30:00 GMT
# ❌ Missing Date (violates HTTP spec)
HTTP/1.1 200 OK
Content-Type: text/html
```javascript
**2. Use correct GMT format**
```javascript
// ✅ Correct format
const date = new Date().toUTCString()
// "Sat, 18 Jan 2026 10:30:00 GMT"
// ❌ Wrong format
const date = new Date().toString()
// "Sat Jan 18 2026 10:30:00 GMT+0000"
3. Keep server clocks synchronized
# Use NTP to keep server time accurate
sudo timedatectl set-ntp true
# Check time synchronization
timedatectl status
```text
**4. Don't manipulate Date for caching tricks**
```http
# ❌ Bad: Faking the Date
Date: Sat, 18 Jan 2025 10:30:00 GMT (when it's actually 2026)
# ✅ Good: Use proper caching headers
Date: Sat, 18 Jan 2026 10:30:00 GMT
Cache-Control: max-age=31536000
5. Include Age header for cached responses
# ✅ Clear cache status
Date: Sat, 18 Jan 2026 10:00:00 GMT
Age: 300
Cache-Control: max-age=3600
```javascript
### For Clients
**1. Use Date for cache calculations**
```javascript
async function fetchWithCacheCheck(url) {
const response = await fetch(url)
const date = new Date(response.headers.get('Date'))
const age = parseInt(response.headers.get('Age') || '0')
const maxAge = parseCacheControl(response.headers.get('Cache-Control'))
const responseAge = age
const freshnessLifetime = maxAge
const isFresh = responseAge < freshnessLifetime
console.log('Response date:', date)
console.log('Is fresh:', isFresh)
return response
}
2. Detect clock skew
fetch('/api/time').then((response) => {
const serverDate = new Date(response.headers.get('Date'))
const clientDate = new Date()
const skew = Math.abs(serverDate - clientDate) / 1000
if (skew > 60) {
console.warn(`Clock skew detected: ${skew} seconds`)
}
})
```javascript
**3. Use for retry-after calculations**
```javascript
fetch('/api/endpoint').then((response) => {
if (response.status === 429) {
const serverDate = new Date(response.headers.get('Date'))
const retryAfter = parseInt(response.headers.get('Retry-After'))
const retryTime = new Date(serverDate.getTime() + retryAfter * 1000)
console.log('Retry after:', retryTime)
}
})
Date Format Examples
HTTP-date Format (RFC 7231)
Date: Sat, 18 Jan 2026 10:30:00 GMT
```javascript
### JavaScript Generation
```javascript
// Correct HTTP date format
const httpDate = new Date().toUTCString()
// "Sat, 18 Jan 2026 10:30:00 GMT"
// ISO format (not for Date header)
const isoDate = new Date().toISOString()
// "2026-01-18T10:30:00.000Z"
Python Generation
from email.utils import formatdate
# Correct HTTP date format
http_date = formatdate(timeval=None, localtime=False, usegmt=True)
# "Sat, 18 Jan 2026 10:30:00 GMT"
```text
## Cache Freshness Calculation
### Formula
```text
response_age = Age header value OR (now - Date header value)
freshness_lifetime = max-age from Cache-Control
response_is_fresh = (response_age < freshness_lifetime)
```text
### Example
```http
Date: Sat, 18 Jan 2026 10:00:00 GMT
Cache-Control: max-age=600
Age: 120
# Current time: Sat, 18 Jan 2026 10:02:00 GMT
# Response age: 120 seconds (from Age header)
# Freshness lifetime: 600 seconds (from max-age)
# Fresh for: 480 more seconds (600 - 120)
Testing Date Header
Using curl
# Check Date header
curl -I https://example.com
# Verbose output to see Date
curl -v https://example.com
# Extract only Date header
curl -s -I https://example.com | grep -i "^Date:"
```javascript
### Using JavaScript
```javascript
// Check server date
fetch('https://api.example.com').then((response) => {
const dateHeader = response.headers.get('Date')
const serverTime = new Date(dateHeader)
const clientTime = new Date()
console.log('Server time:', serverTime)
console.log('Client time:', clientTime)
console.log('Difference:', Math.abs(serverTime - clientTime) / 1000, 'seconds')
})
// Calculate cache freshness
fetch('https://api.example.com/cached').then((response) => {
const date = new Date(response.headers.get('Date'))
const age = parseInt(response.headers.get('Age') || '0')
const cacheControl = response.headers.get('Cache-Control')
const maxAgeMatch = cacheControl.match(/max-age=(\d+)/)
const maxAge = maxAgeMatch ? parseInt(maxAgeMatch[1]) : 0
console.log('Response age:', age, 'seconds')
console.log('Max age:', maxAge, 'seconds')
console.log('Fresh for:', maxAge - age, 'seconds')
})
Related Headers
- Age - How old the response is
- Cache-Control - Caching directives
- Expires - Absolute expiration time
- Last-Modified - When resource was last changed
Frequently Asked Questions
What is the Date header?
Date indicates when the message was generated. Servers should include it in all responses. It uses HTTP-date format in GMT timezone.
What format does Date use?
HTTP-date format: Date: Wed, 21 Oct 2026 07:28:00 GMT. Always use GMT timezone. The format is defined in RFC 9110.
Is Date required?
Servers with a clock should include Date in responses. It is important for caching calculations and debugging. Clients rarely send Date.
How is Date used in caching?
Caches use Date with Age header to calculate response freshness. Date shows when the origin generated the response, Age shows time in cache.