Skip to main content
HTML Validation

Bad value “Expires” for attribute “http-equiv” on element “meta”.

About This HTML Issue

The http-equiv attribute on the <meta> element is designed to simulate certain HTTP response headers directly in HTML. However, the HTML specification only permits a specific set of values: content-type, default-style, refresh, x-ua-compatible, and content-security-policy. Using Expires as a value for http-equiv will trigger a validation error because it falls outside this permitted set.

Historically, some older browsers and HTML versions were more lenient about which values could appear in http-equiv, and developers commonly used <meta http-equiv="Expires" content="0"> or similar patterns to try to prevent page caching. However, this approach was never reliable — browsers and caching proxies handle actual HTTP headers far more consistently than <meta> tag equivalents. Modern HTML formally disallows this value.

Beyond standards compliance, there are practical reasons to avoid this pattern. Many browsers simply ignore unrecognized http-equiv values, meaning the tag does nothing useful. Cache behavior is best controlled at the HTTP level, where servers, CDNs, and proxies all read and respect the headers. Relying on a <meta> tag for caching gives a false sense of control while cluttering your markup with invalid code.

To fix this issue, remove the <meta http-equiv="Expires" ...> tag from your HTML and configure the Expires or Cache-Control HTTP header on your web server.

Examples

Incorrect: Using Expires in http-equiv

This triggers the validation error:

<head>
  <meta charset="UTF-8">
  <meta http-equiv="Expires" content="0">
  <meta http-equiv="Expires" content="Tue, 01 Jan 2025 00:00:00 GMT">
  <title>My Page</title>
</head>

Correct: Remove the invalid <meta> tag

Simply remove the offending tag. Only use valid http-equiv values:

<head>
  <meta charset="UTF-8">
  <title>My Page</title>
</head>

Correct: Valid uses of http-equiv

For reference, here are examples of valid http-equiv values:

<head>
  <meta charset="UTF-8">
  <meta http-equiv="refresh" content="30">
  <meta http-equiv="content-security-policy" content="default-src 'self'">
  <meta http-equiv="default-style" content="main-stylesheet">
  <title>My Page</title>
</head>

Correct: Set cache expiration via server configuration

The proper way to control caching is through HTTP response headers configured on your server.

Apache (.htaccess or server config):

<IfModule mod_expires.c>
  ExpiresActive On
  ExpiresByType text/html "access plus 1 day"
</IfModule>

Or using Cache-Control with mod_headers:

<IfModule mod_headers.c>
  Header set Cache-Control "no-cache, no-store, must-revalidate"
  Header set Expires "0"
</IfModule>

Nginx:

location ~* \.html$ {
  expires 1d;
  add_header Cache-Control "public, no-transform";
}

To prevent caching entirely in Nginx:

location ~* \.html$ {
  expires -1;
  add_header Cache-Control "no-store, no-cache, must-revalidate";
}

If you don’t have access to server configuration, many server-side languages let you set headers programmatically. For example, in PHP:

<?php
header("Expires: Tue, 01 Jan 2030 00:00:00 GMT");
header("Cache-Control: public, max-age=86400");
?>

By handling cache expiration at the server level, you get reliable behavior across all browsers, proxies, and CDNs — while keeping your HTML clean and standards-compliant.

Find issues like this automatically

Rocket Validator scans thousands of pages in seconds, detecting HTML issues across your entire site.

Help us improve our guides

Was this guide helpful?
🌍 Trusted by teams worldwide

Validate at scale.
Ship accessible websites, faster.

Automated HTML & accessibility validation for large sites. Check thousands of pages against WCAG guidelines and W3C standards in minutes, not days.

Scheduled Reports
API Access
Open Source Standards
$7 / 7 days

Pro Trial

Full Pro access. Cancel anytime.

Start Pro Trial →

Join teams across 40+ countries