HTTP

Header

Refresh Header

Learn how the Refresh header instructs browsers to reload or redirect after a delay. Understand its use cases, limitations, and better alternatives.

6 min read beginner Try in Playground

TL;DR: Instructs browsers to automatically reload or redirect after a delay. Use proper HTTP redirects (301/302) instead for better UX and SEO.

What is Refresh?

The Refresh header instructs the browser to automatically reload the current page or redirect to a different URL after a specified number of seconds. It’s like setting a timer that says “in 5 seconds, go to this page” or “reload this page every 30 seconds.”

This header is non-standard but widely supported across browsers. It’s commonly used for page redirects, auto-refreshing dashboards, and “you will be redirected” pages.

How Refresh Works

Server sends Refresh header:

HTTP/1.1 200 OK
Refresh: 5; url=https://example.com/home
Content-Type: text/html

<html>
  <body>
    <p>You will be redirected in 5 seconds...</p>
  </body>
</html>
```text

The browser waits 5 seconds, then automatically redirects to the specified URL.

## Syntax

```http
Refresh: <seconds>
Refresh: <seconds>; url=<url>

Values

  • seconds - Delay in seconds before refresh/redirect
  • url - Optional URL to redirect to (if omitted, reloads current page)

Common Examples

Auto Reload Current Page

Refresh: 30
```text

Reload the page every 30 seconds.

### Redirect After Delay

```http
Refresh: 3; url=https://example.com/home

Redirect to home page after 3 seconds.

Immediate Redirect

Refresh: 0; url=https://example.com/new-location
```text

Redirect immediately (0 second delay).

### Relative URL Redirect

```http
Refresh: 5; url=/dashboard

Redirect to relative URL after 5 seconds.

Real-World Scenarios

Post-Login Redirect

POST /login HTTP/1.1
Content-Type: application/x-www-form-urlencoded

username=user&password=pass

HTTP/1.1 200 OK
Refresh: 2; url=/dashboard
Content-Type: text/html

<html>
  <body>
    <h1>Login Successful!</h1>
    <p>Redirecting to dashboard in 2 seconds...</p>
  </body>
</html>
```text

### Auto-Refreshing Dashboard

```http
GET /monitoring/dashboard HTTP/1.1

HTTP/1.1 200 OK
Refresh: 10
Content-Type: text/html

<html>
  <body>
    <h1>Server Status Dashboard</h1>
    <p>Auto-refreshing every 10 seconds...</p>
    <div id="metrics">
      CPU: 45%, Memory: 60%, Disk: 75%
    </div>
  </body>
</html>

Payment Processing Page

POST /checkout/process HTTP/1.1

HTTP/1.1 200 OK
Refresh: 5; url=/checkout/confirmation
Content-Type: text/html

<html>
  <body>
    <h1>Processing your payment...</h1>
    <p>Please wait. You will be redirected shortly.</p>
  </body>
</html>
```text

### Session Expired Redirect

```http
GET /account HTTP/1.1

HTTP/1.1 200 OK
Refresh: 3; url=/login?expired=true
Content-Type: text/html

<html>
  <body>
    <h1>Session Expired</h1>
    <p>Redirecting to login page in 3 seconds...</p>
  </body>
</html>

Server Implementation

Express.js (Node.js)

const express = require('express')
const app = express()

// Auto-reload page
app.get('/dashboard', (req, res) => {
  res.setHeader('Refresh', '30')
  res.send(`
    <html>
      <body>
        <h1>Dashboard</h1>
        <p>Auto-refreshing every 30 seconds...</p>
        <p>Current time: ${new Date().toLocaleTimeString()}</p>
      </body>
    </html>
  `)
})

// Redirect after delay
app.post('/login', (req, res) => {
  // Validate credentials...

  res.setHeader('Refresh', '2; url=/dashboard')
  res.send(`
    <html>
      <body>
        <h1>Login Successful!</h1>
        <p>Redirecting to dashboard in 2 seconds...</p>
      </body>
    </html>
  `)
})

// Immediate redirect (alternative to 302)
app.get('/old-url', (req, res) => {
  res.setHeader('Refresh', '0; url=/new-url')
  res.send(`
    <html>
      <body>
        <p>This page has moved. Redirecting...</p>
      </body>
    </html>
  `)
})

// Processing page with countdown
app.post('/process', (req, res) => {
  const delay = 5

  res.setHeader('Refresh', `${delay}; url=/result`)
  res.send(`
    <html>
      <head>
        <script>
          let seconds = ${delay};
          setInterval(() => {
            seconds--;
            if (seconds >= 0) {
              document.getElementById('countdown').textContent = seconds;
            }
          }, 1000);
        </script>
      </head>
      <body>
        <h1>Processing...</h1>
        <p>Redirecting in <span id="countdown">${delay}</span> seconds...</p>
      </body>
    </html>
  `)
})
```javascript

### FastAPI (Python)

```python
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
from datetime import datetime

app = FastAPI()

@app.get("/dashboard", response_class=HTMLResponse)
async def dashboard():
    current_time = datetime.now().strftime("%H:%M:%S")

    return HTMLResponse(
        content=f"""
        <html>
          <body>
            <h1>Dashboard</h1>
            <p>Auto-refreshing every 30 seconds...</p>
            <p>Current time: {current_time}</p>
          </body>
        </html>
        """,
        headers={"Refresh": "30"}
    )

@app.post("/login", response_class=HTMLResponse)
async def login():
    # Validate credentials...

    return HTMLResponse(
        content="""
        <html>
          <body>
            <h1>Login Successful!</h1>
            <p>Redirecting to dashboard in 2 seconds...</p>
          </body>
        </html>
        """,
        headers={"Refresh": "2; url=/dashboard"}
    )

@app.get("/old-url", response_class=HTMLResponse)
async def old_url():
    return HTMLResponse(
        content="""
        <html>
          <body>
            <p>This page has moved. Redirecting...</p>
          </body>
        </html>
        """,
        headers={"Refresh": "0; url=/new-url"}
    )

Django

from django.http import HttpResponse
from datetime import datetime

def dashboard(request):
    current_time = datetime.now().strftime("%H:%M:%S")

    response = HttpResponse(f"""
        <html>
          <body>
            <h1>Dashboard</h1>
            <p>Auto-refreshing every 30 seconds...</p>
            <p>Current time: {current_time}</p>
          </body>
        </html>
    """)
    response['Refresh'] = '30'

    return response

def login_success(request):
    response = HttpResponse("""
        <html>
          <body>
            <h1>Login Successful!</h1>
            <p>Redirecting to dashboard in 2 seconds...</p>
          </body>
        </html>
    """)
    response['Refresh'] = '2; url=/dashboard'

    return response
```nginx

### Nginx

```nginx
server {
    listen 80;
    server_name example.com;

    # Auto-refresh monitoring page
    location /monitoring {
        add_header Refresh "10";
        root /var/www/html;
    }

    # Redirect with delay
    location /old-page {
        add_header Refresh "3; url=/new-page";
        return 200 "This page has moved. Redirecting...";
    }
}

Best Practices

For Servers

1. Use proper redirects for permanent moves

# ❌ Don't use Refresh for permanent redirects
Refresh: 0; url=/new-location

# ✅ Use proper 301/308 redirect
HTTP/1.1 301 Moved Permanently
Location: /new-location
```javascript

**2. Provide visual feedback for delays**

```html
<!-- ✅ Show countdown for user experience -->
<h1>Processing...</h1>
<p>Redirecting in <span id="countdown">5</span> seconds...</p>

<script>
  let seconds = 5
  setInterval(() => {
    seconds--
    document.getElementById('countdown').textContent = seconds
  }, 1000)
</script>

3. Use reasonable refresh intervals

# ✅ Reasonable for real-time data
Refresh: 10

# ❌ Too frequent, wastes resources
Refresh: 1

# ❌ Too long for meaningful updates
Refresh: 300
```text

**4. Include a manual link**

```html
<!-- ✅ Provide manual option -->
<p>You will be redirected in 3 seconds...</p>
<p>Or <a href="/dashboard">click here</a> to continue immediately.</p>

5. Consider using JavaScript alternatives

// ✅ More control with JavaScript
setTimeout(() => {
  window.location.href = '/dashboard'
}, 3000)

// Or meta tag
<meta http-equiv="refresh" content="3; url=/dashboard">
```javascript

### For Clients

**1. Handle Refresh header**

```javascript
// Most browsers handle this automatically
// But you can detect it:
fetch('/page').then((response) => {
  const refresh = response.headers.get('Refresh')
  if (refresh) {
    console.log('Page will refresh:', refresh)
  }
})

2. Provide cancellation option

<!-- Allow users to cancel auto-redirect -->
<p>Redirecting in <span id="countdown">5</span> seconds...</p>
<button onclick="clearTimeout(redirectTimer)">Cancel</button>

<script>
  const redirectTimer = setTimeout(() => {
    window.location.href = '/dashboard'
  }, 5000)
</script>
```text

## Refresh vs Other Redirect Methods

### Refresh Header

```http
HTTP/1.1 200 OK
Refresh: 3; url=/new-page

<html>Redirecting...</html>

Pros: Shows content while waiting Cons: Non-standard, can’t be cached by proxies

Location Header (301/302)

HTTP/1.1 302 Found
Location: /new-page
```text

Pros: Standard, immediate, cacheable
Cons: No delay option, no intermediate content

### HTML Meta Tag

```html
<meta http-equiv="refresh" content="3; url=/new-page" />

Pros: Works without server-side changes Cons: Only in HTML, not flexible

JavaScript

setTimeout(() => {
  window.location.href = '/new-page'
}, 3000)
```http

Pros: Most flexible, can cancel, update UI
Cons: Requires JavaScript enabled

## Common Use Cases

### Auto-Refreshing Dashboards

```http
Refresh: 15

Keep monitoring dashboards up-to-date.

”Please Wait” Pages

Refresh: 5; url=/result
```text

Payment processing, job submission confirmation.

### Session Timeout Redirect

```http
Refresh: 3; url=/login?timeout=true

Redirect after session expires.

Temporary Maintenance Page

Refresh: 60
```text

Auto-refresh to check if site is back online.

### Post-Action Confirmation

```http
Refresh: 2; url=/home

After form submission, show success then redirect.

Accessibility Considerations

1. Provide sufficient time

# ✅ Give users time to read
Refresh: 5; url=/next-page

# ❌ Too fast for many users
Refresh: 1; url=/next-page
```text

**2. Announce to screen readers**

```html
<div role="status" aria-live="polite">You will be redirected in 5 seconds</div>

3. Avoid auto-refresh for content pages

# ❌ Bad for reading content
Refresh: 30  (on article page)

# ✅ Only for real-time data
Refresh: 30  (on dashboard/monitoring)
```text

## Testing Refresh Header

### Using curl

```bash
# Check for Refresh header
curl -I https://example.com/page

# View full response
curl -v https://example.com/page

# Extract Refresh header
curl -sI https://example.com/page | grep -i "^Refresh:"

Using JavaScript

// Check for Refresh header
fetch('/page').then((response) => {
  const refresh = response.headers.get('Refresh')

  if (refresh) {
    const match = refresh.match(/(\d+)(?:;\s*url=(.+))?/)
    if (match) {
      const delay = parseInt(match[1])
      const url = match[2]

      console.log(`Refresh in ${delay} seconds`)
      if (url) {
        console.log(`Redirect to: ${url}`)
      } else {
        console.log('Reload current page')
      }
    }
  }
})
```javascript

### Browser Testing

```javascript
// Monitor Refresh in DevTools
// Network tab -> Click request -> Headers -> Look for Refresh

// Or use console
const observer = new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    console.log('Refresh detected:', entry)
  }
})
observer.observe({ entryTypes: ['navigation'] })

Frequently Asked Questions

What is the Refresh header?

Refresh tells browsers to reload the page or redirect after a delay. Equivalent to meta http-equiv refresh. Example: Refresh: 5; url=https://example.com

Should I use Refresh for redirects?

No, use proper HTTP redirects (301, 302, 303, 307, 308) instead. Refresh is not a standard HTTP header and has accessibility and SEO issues.

What are the problems with Refresh?

It breaks the back button, confuses screen readers, is not a proper HTTP standard, and search engines may not follow it correctly. Use HTTP redirects instead.

When might Refresh be acceptable?

Only for auto-refreshing dashboards or status pages where users expect periodic updates. Even then, JavaScript or Server-Sent Events are better alternatives.

Keep Learning