Redirects

Htaccess redirect: why the default code is temporary

6 min readUpdated

An .htaccess redirect is a rule in Apache's per-directory configuration file that sends a request to another address. Unless you name a status, it is temporary: Apache's Redirect directive and the [R] flag of RewriteRule both return a 302 by default. For a page that has moved for good, among the kinds of redirect, that is the wrong one.

What .htaccess is

An .htaccess file is a configuration file that Apache reads from a directory of the site itself. Apache's documentation describes these as "distributed configuration files" that "provide a way to make configuration changes on a per-directory basis": the directives in the file apply to its directory and to every directory below it.

The file exists for people who cannot edit the server's main configuration, which is the usual situation on shared hosting and with content management systems that ship their own .htaccess. Apache is direct about the preference: "If you have access to the main server configuration file, you should put all of your configuration there instead of in .htaccess files." The file is read on every request, while the main configuration is loaded once at start.

Files higher up still count. Apache applies directives "in the order that they are found", so an .htaccess in a subdirectory can override one in a directory above it, which in turn may override the main configuration. A redirect that behaves oddly in one folder is often a rule from a parent folder that nobody remembered.

Only Apache, and servers built to imitate it, read the file. On nginx it is an ordinary file that does nothing; redirects there are written as nginx rules.

The default is a 302

Both ways of writing a redirect in .htaccess default to a temporary code. The Redirect directive of the mod_alias module documents its status options with "temp Returns a temporary redirect status (302). This is the default." The [R] flag of RewriteRule in mod_rewrite says the same in other words: a "302 status code being used by default if none is specified."

That matters because Google treats the two classes differently. Its documentation on redirects, last updated on and checked on , says a temporary redirect is followed but not used "as a signal that the redirect target should be canonical." A site that moved its pages with bare Redirect lines has told search that every move is temporary, and the old addresses stay in results. The 302 redirect page covers what that code is actually for.

The fix is to name the status every time.

Naming the status

The status goes into the rule itself, as a word or a number. Apache's mod_alias documentation, checked on , gives these examples:

Redirect permanent "/one" "http://example.com/two"
Redirect 303 "/three" "http://example.com/other"

The first sends a permanent 301; the second, a 303 See Other. The recognised words are permanent for 301, temp for 302, seeother for 303 and gone for 410, and any other status can be given as its number.

The rewrite flag works the same way: [R=301] instead of [R], or the symbolic name permanent, which the flag documentation lists alongside temp and seeother.

Redirect or RewriteRule

Redirect is the simple tool: it matches the start of a path and sends it somewhere else. Apache's documentation sets out its rules plainly. The old path is "a case-sensitive (%-decoded) path beginning with a slash. A relative path is not allowed." The new address may be a full URL or a path on the same host.

RewriteRule is the tool for conditions: patterns, parts of the address captured and reused, rules that apply only to a certain host or protocol. It is also easier to get wrong, because a pattern that matches more than intended redirects more than intended. Apache's own guide to redirecting and remapping works through the common cases, and in its simplest one notes that the Redirect directive could be used instead.

A reasonable order is to reach for Redirect first and move to RewriteRule only when a condition is required. The most common condition is the protocol or the host, as in moving every address to HTTPS, which HTTP to HTTPS redirects covers end to end.

When a rule does nothing

An .htaccess redirect can be correct and still never run. Apache's documentation states the reason: "The default value of AllowOverride is None. This means .htaccess files are completely ignored unless you explicitly enable them for a directory."

The Redirect directive needs the FileInfo override; its documentation lists "Override: FileInfo". If the server's configuration does not allow that class of directive for the directory, the rule does not take effect. On shared hosting this is normally arranged for you; on a server you configured yourself it may not be.

The symptom is a rule that looks right and an address that does not move. Before rewriting the rule, check whether the server reads the file at all.

Checking the rule

The only reliable check is the live response. Request the old address and read the status line and the Location header that come back: a moved page should answer with 301 or 308 and the new address, in one hop. A forgotten status shows up there as a 302; how a trace reads each hop and its status is covered under redirect tracing.

Check after every change, and include an address with a query string and one with an unusual character among the samples, since those are where patterns most often surprise.

FAQ

How do I make an .htaccess redirect permanent?

Name the status in the rule. With the Redirect directive, write permanent or 301 before the old path, as in Apache's own example. With RewriteRule, use the flag [R=301] rather than a bare [R]. Without a status, both default to a temporary 302.

Why is my .htaccess redirect a 302?

Because that is Apache's default. The Redirect directive returns 302 unless told otherwise, and the [R] flag of RewriteRule does the same when no status is given. Add the status explicitly, then confirm with a live request that the response is a 301.

Should I use Redirect or RewriteRule?

Use Redirect when one path maps to another; it is simpler and harder to get wrong. Use RewriteRule when the redirect depends on a condition, such as the host, the protocol or a pattern in the path. In both, name the status, since each defaults to a temporary redirect.

Does .htaccess work on nginx?

No. The file is read by Apache and by servers compatible with it; nginx ignores it and uses its own configuration for redirects. If a site has moved from Apache to nginx, rules left in .htaccess stop working without any error, and every redirect in them needs to be moved to the new server.