3xx Redirection Codes
Introduction
3xx redirection status codes are HTTP responses that tell the client that the requested resource is not being delivered directly from the original request target. Instead of returning the final content immediately, the server instructs the client to take another step. In most cases, that step is to follow another URL provided in the Location header. In some cases, such as 304 Not Modified, the additional step is not another request at all; the client should use its cached copy of the resource.
Redirection is common on websites, but it also matters in API design and API testing. A company may move an endpoint from one version to another, redirect traffic from HTTP to HTTPS, route requests through a new domain, send clients to a temporary maintenance endpoint, or optimize caching so clients do not repeatedly download unchanged content. If testers understand only 2xx, 4xx, and 5xx responses, they may miss important behavior around migration, caching, routing, and method preservation.
The key idea is that a 3xx response is not a normal success response and it is not automatically an error. It is a redirection signal. The server is saying that the client must take additional action to complete the request. API testers need to verify whether the returned redirect code is correct, whether the target URL is correct, whether the redirect is temporary or permanent, whether the request method is preserved when required, and whether cached resources behave as expected.
What Are 3xx Redirection Codes?
The 3xx status code range covers HTTP responses from 300 to 399. These responses indicate that the requested resource may be available, but the client must perform an additional action before it receives the final result. Usually, that action is following a different URI. The new URI is commonly supplied in the Location response header.
A simple definition is this: 3xx redirection codes tell the client that the requested resource has moved, is available somewhere else, can be retrieved another way, or can be served from cache. The redirection response itself is not usually the final business response. If a client receives 301 Moved Permanently with a Location header pointing to a new endpoint, the client must request the new endpoint to get the final response. If the client receives 304 Not Modified, it should use the local cached response body that it already has.
In API testing, it is important to decide whether redirects should be followed automatically by the tool or inspected manually. Many clients and libraries automatically follow redirects and show only the final response. That can hide defects. For example, a test may show 200 OK after following a redirect, while the original API returned an incorrect 302 Found instead of 308 Permanent Redirect. When redirect behavior is part of the requirement, tests should inspect the first response, not only the final followed response.
Common 3xx Status Codes
The most important redirection codes for API testers are 301 Moved Permanently, 302 Found, 303 See Other, 304 Not Modified, 307 Temporary Redirect, and 308 Permanent Redirect. 300 Multiple Choices is also part of the family, though it is less common in typical REST APIs.
301 and 308 are permanent redirects. They tell the client that the old URL should no longer be treated as the correct long-term location. 302 and 307 are temporary redirects. They tell the client that the resource is temporarily available elsewhere, but the original URL may still be valid in the future. 303 tells the client to retrieve another URI using GET, often after a POST operation. 304 tells the client that its cached copy is still valid.
The distinction between these codes matters because clients, caches, browsers, search engines, API gateways, and SDKs may handle them differently. A permanent redirect can be cached or stored aggressively. A temporary redirect should not cause clients to permanently replace the original URL. A method-preserving redirect is critical when the original request uses POST, PUT, PATCH, or DELETE.
300 Multiple Choices
300 Multiple Choices indicates that the requested resource has more than one possible representation and that the client or user should choose one. A server might use it when a document is available as PDF, Word, and HTML, or when a resource exists in different languages or media types. The response should provide enough information for the client to select a representation.
This status code is not common in everyday JSON REST APIs because content negotiation is often handled using request headers such as Accept and Accept-Language. However, it remains useful to understand because it represents a redirection-style choice rather than a direct success response. The server is not saying that one final representation has been returned; it is saying there are multiple options.
When testing 300 Multiple Choices, verify that the response clearly lists the available options, that each option is valid, and that the client can request the selected representation successfully. If the API uses links in the response body, validate that those links are correct and stable. If the API depends on content negotiation headers, validate that specific headers return the intended representation directly and that ambiguous requests are handled consistently.
301 Moved Permanently
301 Moved Permanently means the requested resource has permanently moved to a new URL. The response normally includes a Location header with the new location. Clients should update bookmarks, cached endpoint references, and future requests to use the new URL.
An example API migration may look like this:
GET /api/v1/products
The server may respond:
HTTP/1.1 301 Moved Permanently
Location: /api/v2/products
The client should use the new endpoint for future requests:
GET /api/v2/products
301 is common when URL structure changes permanently. A website may move from one domain to another. An API may migrate from an older public path to a new version. A service may enforce canonical URLs. A company may move documentation, media files, or public resources to a new domain. In SEO, 301 redirects are especially important because they tell search engines that the move is permanent.
In API testing, verify that the Location header points to the correct destination, that the destination returns the expected final response, and that old endpoints are redirected only when the migration is intentional. Also confirm whether the API client should follow the redirect automatically or receive the redirect response and handle it explicitly.
Testing 301 Moved Permanently
Testing 301 Moved Permanently requires attention to long-term behavior. A permanent redirect tells clients that the old URL should not be used anymore. Therefore, the test should confirm not only that the redirect exists, but also that it points to the correct stable replacement.
Start by disabling automatic redirect following in the API client if possible. This allows the test to inspect the original 301 response. Validate the exact status code, the presence of the Location header, and the value of that header. Then make a second request to the redirected URL and validate the final response. This proves both the redirect contract and the target endpoint behavior.
Also test incorrect redirect targets. A Location header that points to a staging domain, internal host name, local path, or misspelled endpoint can break clients and expose internal architecture details. If the redirect is public, the target should be appropriate for production users. If the API supports multiple environments, make sure redirects are environment-aware and do not point QA traffic to production or production traffic to QA.
For non-GET methods, be careful with 301. Some older clients may change POST to GET when following a 301 redirect. If method preservation is required, 308 Permanent Redirect is usually a clearer modern choice. A test plan should include client behavior, not only server behavior, when permanent redirects affect write operations.
302 Found
302 Found is a temporary redirect. It means the requested resource is temporarily available at another location, but the client should continue to use the original URL for future requests. The response usually includes a Location header pointing to the temporary target.
An example may look like this:
GET /offers
The server responds:
HTTP/1.1 302 Found
Location: /offers-holiday-sale
The client follows the temporary location to view the promotional page. However, when the promotion ends, the original /offers URL should still be the correct entry point. This is the practical difference between 301 and 302. A 301 says "this moved permanently." A 302 says "go here for now."
In APIs, 302 may appear during login flows, temporary routing, maintenance windows, geographic routing, or gateway-level behavior. It is more common in browser flows than pure REST APIs, but testers still encounter it when APIs are part of web applications, OAuth flows, file downloads, or redirects from old routes to temporary resources.
Testing 302 Found
Testing 302 Found starts with verifying that the redirect is truly temporary. If the business rule says the endpoint has moved permanently, 301 or 308 may be more appropriate. If the redirect is only for temporary routing, maintenance, or a short-lived campaign, 302 may be correct.
As with 301 testing, disable automatic redirect following when inspecting redirect behavior. Validate the original status code and Location header. Then follow the Location URL and verify the final response. If authentication is involved, confirm that the redirect does not lose or expose tokens, session cookies, or sensitive query parameters.
Be cautious with request methods. Historically, some clients changed POST to GET after receiving a 302 response. For browser navigation this may be acceptable in some flows, but for API write operations it can be dangerous. If the original request method and body must be preserved, use 307 Temporary Redirect instead of relying on 302.
Also check caching. A temporary redirect should not be cached like a permanent redirect unless explicit cache headers say so. If a client caches a temporary redirect too aggressively, users may continue being sent to the temporary target after the temporary condition is gone.
303 See Other
303 See Other tells the client to retrieve the result from another URI using the GET method. It is commonly used after a POST request when the server wants the client to view or fetch the created or processed result from another location.
For example, a client may submit an order:
POST /orders
The server may respond:
HTTP/1.1 303 See Other
Location: /orders/1001
The client then performs:
GET /orders/1001
This is useful when the server does not want the client to repeat the original POST to view the result. The redirect target is retrieved using GET, which helps avoid duplicate form submissions or repeated state-changing actions.
For API testers, the key point is that 303 intentionally changes the follow-up request to GET. This makes it different from 307 and 308, which preserve the original method. A 303 response after a POST can be valid when the goal is to direct the client to a result resource rather than repeat the original operation.
304 Not Modified
304 Not Modified is different from many other 3xx codes because it does not redirect the client to a new URL. Instead, it tells the client that the requested resource has not changed since the client's cached version. The client should use its cached copy rather than downloading the resource again.
A typical conditional request may look like this:
GET /logo.png
If-Modified-Since: Tue, 30 Jun 2026 10:00:00 GMT
If the resource has not changed, the server may respond:
HTTP/1.1 304 Not Modified
The server does not send the full image again. The client uses its local cached copy. This reduces bandwidth, improves response time, and lowers server load. Conditional requests may also use ETags through headers such as If-None-Match.
In API and web testing, 304 Not Modified is important for performance and caching validation. It is common for images, CSS files, JavaScript files, documents, and cacheable API responses. It may not be used for dynamic sensitive data unless caching is carefully controlled.
Testing 304 Not Modified
Testing 304 Not Modified requires a cache-aware approach. First, request the resource normally and capture caching headers such as ETag, Last-Modified, Cache-Control, and Expires. Then send a conditional request using If-None-Match or If-Modified-Since. If the resource has not changed, the server should return 304 Not Modified.
A 304 response should not include the full response body. This is one of the most important validation points. If the server returns 304 but still sends the complete resource body, the caching benefit is lost and the response is semantically incorrect. The client should rely on its cached representation.
Also test the changed-resource case. If the resource changes after the client caches it, the server should return the new content with a final success code such as 200 OK, not 304 Not Modified. Otherwise, clients may continue displaying stale data. For APIs, this can create serious business defects if users see outdated prices, statuses, balances, permissions, or configuration values.
Security matters too. Do not cache private data incorrectly. If a user-specific API response is cached and later reused for the wrong user, that is a serious data exposure issue. Tests should verify that sensitive responses use appropriate cache controls and that 304 behavior is applied only where it is safe.
307 Temporary Redirect
307 Temporary Redirect means the resource is temporarily available at another location, and the client must repeat the request using the same HTTP method and request body. This method-preservation rule is the main reason 307 exists.
Consider this request:
POST /payments
Content-Type: application/json
{
"amount": 100,
"currency": "USD"
}
The server may respond:
HTTP/1.1 307 Temporary Redirect
Location: /payments-temp
The client should resend the request as:
POST /payments-temp
Content-Type: application/json
{
"amount": 100,
"currency": "USD"
}
The method remains POST, and the request body is preserved. This is different from old behavior around 302, where some clients converted the follow-up request to GET. For APIs that modify data, method preservation is critical. A payment, order, upload, or update request should not silently turn into a GET request because of redirect handling.
Testing 307 Temporary Redirect
Testing 307 Temporary Redirect should focus on method and body preservation. If the original request is POST, the redirected request must also be POST. If the original request is PUT, PATCH, or DELETE, that method must also be preserved. The request body should not be lost, modified, or resent incorrectly.
This often requires inspecting logs or using a client that exposes redirected requests. A high-level test may only show the final response, but the important evidence is whether the second request used the correct method. Server logs on the redirect target can confirm what method and body were received.
Also test temporary behavior. The original URL should remain the long-term URL. A 307 redirect may be used during maintenance, traffic routing, temporary infrastructure changes, or failover. Once the temporary condition ends, the original endpoint should work normally. If the redirect becomes permanent, 308 Permanent Redirect may be more appropriate.
Security validation is essential for redirected write operations. Authorization headers, cookies, tokens, and request bodies should not be sent to an untrusted domain. Redirect targets should be controlled and expected. Open redirect weaknesses can become serious vulnerabilities if clients are redirected to malicious locations.
308 Permanent Redirect
308 Permanent Redirect means the resource has permanently moved to a new location, and the client must preserve the original HTTP method and request body when making the redirected request. It combines the permanent nature of 301 with the method-preservation guarantee of 307.
For example:
PUT /users/101
Content-Type: application/json
{
"name": "John Smith"
}
The server may respond:
HTTP/1.1 308 Permanent Redirect
Location: /customers/101
The client should repeat:
PUT /customers/101
Content-Type: application/json
{
"name": "John Smith"
}
This code is useful for modern APIs that need permanent endpoint migration while preserving write semantics. If an API permanently renames /users to /customers, and clients may send PUT, PATCH, or DELETE requests, 308 communicates the migration more safely than 301 for method-sensitive operations.
301 vs 308 and 302 vs 307
The comparison between 301 and 308 is about permanent redirects and method preservation. Both indicate a permanent move. The practical difference is that 308 explicitly requires the client to preserve the HTTP method and request body. With 301, older clients may not behave consistently for non-GET requests. For a website page moved permanently, 301 is common. For a modern API endpoint that receives write requests, 308 may be safer.
The comparison between 302 and 307 is similar, but for temporary redirects. Both indicate that the resource is temporarily available elsewhere. 307 explicitly preserves the method and body. If the request is a browser navigation or simple GET, 302 may be enough. If the request is POST, PUT, PATCH, or DELETE and the method must remain unchanged, 307 is clearer.
This distinction is important in interviews and in real project testing. Many defects occur because teams use familiar older codes without thinking about method behavior. A redirect for a payment POST, file upload, or data update should not accidentally become a GET. When testers see redirects around write operations, they should immediately ask whether method preservation is required and whether the chosen status code guarantees it.
3xx Responses in REST APIs
Most REST APIs primarily use final success and error codes such as 200 OK, 201 Created, 400 Bad Request, 401 Unauthorized, 404 Not Found, and 500 Internal Server Error. Because of this, some testers assume 3xx responses are only browser behavior. That assumption is incomplete. REST APIs can and do use redirects in specific situations.
API version migration is one common case. An organization may move clients from /api/v1 to /api/v2. Endpoint relocation is another case. A service may split into multiple services, causing old paths to redirect to new service-specific paths. Caching optimization can produce 304 Not Modified. Temporary maintenance or traffic-routing decisions can produce 302 or 307. Domain or protocol changes can redirect traffic from HTTP to HTTPS or from an old API host to a new host.
However, redirects in APIs should be used carefully. Machine clients may not handle redirects the same way browsers do. Some API clients disable redirects by default. Some automatically follow redirects but drop headers. Some preserve authorization headers only for same-host redirects. Some hide intermediate responses. A robust API design should document redirect behavior, and robust API tests should validate how important clients are expected to behave.
API Testing Considerations
When testing 3xx responses, first validate the exact status code. A permanent redirect should not accidentally return a temporary redirect. A method-preserving redirect should not use a status code that allows method changes. A caching response should not be treated like a moved-resource redirect. The exact code communicates the expected client behavior.
Next, validate the Location header whenever it is required. The target should be correct, reachable, environment-appropriate, and safe. It should not point to a broken endpoint, internal development host, insecure HTTP URL when HTTPS is required, or untrusted external domain. If the URL is relative, confirm that clients resolve it correctly. If it is absolute, confirm that the domain and scheme are correct.
Then validate redirect following. Some tests should inspect the initial redirect response. Other tests should follow the redirect and validate the final response. Both are useful, but they answer different questions. Inspecting the first response proves the redirect contract. Following the redirect proves the client can reach the final resource.
For 307 and 308, explicitly verify that the original HTTP method and body are preserved. For 304, verify caching headers, conditional request behavior, absence of response body, and stale-data prevention. For security-sensitive flows, verify that redirects do not leak credentials, tokens, session IDs, or private information.
Real-World Examples
A company migrating from api.company.com/v1 to api.company.com/v2 may use 301 Moved Permanently for old read-only endpoints. Clients are told to update future requests to the new version. API tests should ensure that old endpoints redirect to the correct v2 paths and that the v2 endpoints return the expected data.
An e-commerce site may temporarily redirect users from a normal offers page to a holiday campaign page using 302 Found. The redirect is temporary because the normal URL should remain valid after the campaign. Tests should confirm that the redirect starts and stops according to the campaign configuration.
A browser requesting a company logo may send an If-Modified-Since or If-None-Match header. If the logo has not changed, the server returns 304 Not Modified, and the browser uses its cached copy. This saves bandwidth and speeds up rendering. Tests should confirm that changed assets return new content and unchanged assets return 304 when appropriate.
A payment service under temporary maintenance may return 307 Temporary Redirect to route POST payment requests to another payment server while preserving the original method and body. This is safer than a redirect that may convert POST to GET. Tests should confirm that the target receives the same POST body and that authorization remains valid.
A company that permanently renames a customer endpoint from /users to /customers may use 308 Permanent Redirect so clients preserve PUT, PATCH, or DELETE methods. This helps modern API clients migrate without changing the meaning of write operations.
Common Misconceptions
A common misconception is that 3xx responses are errors. They are not errors by themselves. They indicate that another action is required. A broken redirect target can cause failure, but the redirect status code itself represents routing, movement, or caching behavior.
Another misconception is that 301 and 302 are basically the same. They are not. 301 is permanent, while 302 is temporary. This affects caching, client behavior, search engines, and long-term endpoint usage. Using the wrong one can cause clients to continue using an old URL or permanently cache a temporary route.
A third misconception is that 307 and 308 are just modern names for 302 and 301. The important difference is method preservation. 307 and 308 tell the client to repeat the request using the same method and body. This matters for API write operations.
Another misconception is that automatic redirect following is always enough in API testing. If the tool follows the redirect and returns a final 200 OK, the test may miss an incorrect redirect status code, missing Location header, insecure redirect target, or method change. When redirect behavior is part of the contract, inspect the redirect response directly.
Best Practices
Use 301 Moved Permanently for permanent URL changes when method preservation is not a concern, especially for web pages and read-only resources. Use 308 Permanent Redirect for permanent API moves where the original HTTP method and request body must be preserved.
Use 302 Found for temporary redirects where method preservation is not critical. Use 307 Temporary Redirect for temporary redirects where the same method and body must be repeated. Use 303 See Other when a POST or similar request should direct the client to retrieve a result using GET. Use 304 Not Modified for conditional caching when the cached representation is still valid.
Always include a valid Location header when the redirect code requires a new location. Keep redirect targets stable, safe, and environment-aware. Avoid redirect chains where one URL redirects to another, then another, then another. Redirect chains slow down clients, complicate debugging, and may break automation.
Document redirect behavior in the API specification. If clients are expected to follow redirects, say so. If authorization headers must be preserved only for same-host redirects, document that. If an endpoint is deprecated and redirects for a migration period, document the deadline and the replacement path.
For testing, verify exact status code, Location header, final response, method preservation, caching behavior, and security implications. Redirects are simple when they work, but confusing when they fail because multiple requests and layers may be involved.
Troubleshooting Redirect Problems
When a redirect problem occurs, first identify whether the client is seeing the initial redirect response or only the final response after following it. Many debugging mistakes happen because one person looks at server logs showing a 301 while another person looks at an API client showing a final 200. Both may be true. They are observing different parts of the flow.
Next, inspect the Location header. Check spelling, scheme, host, path, query parameters, and environment. If authentication is involved, verify whether the redirect target is allowed to receive credentials. Some clients intentionally remove authorization headers when redirected to a different host. This can cause a final 401 Unauthorized even though the initial redirect was correct.
Then check the HTTP method. If a POST request becomes a GET after redirection, the chosen status code or client behavior may be wrong for the scenario. Use 307 or 308 when method preservation is required. For caching issues, compare ETag and Last-Modified values and confirm whether the resource actually changed.
Finally, watch for redirect loops. A redirect loop occurs when URL A redirects to URL B and URL B redirects back to URL A, or when a chain never reaches a final response. Browsers and clients eventually stop following the loop, but the user experience and automation result will fail. Tests should catch these problems by limiting redirect depth and reporting the redirect chain clearly.
Interview-Ready Explanation
3xx redirection HTTP status codes indicate that the requested resource is available, but the client must take additional action to complete the request. Usually this means following another URL provided in the Location header, although 304 Not Modified tells the client to use its cached copy instead of downloading the resource again.
Common 3xx codes include 301 Moved Permanently, which means the resource has permanently moved; 302 Found, which means the resource is temporarily available at another location; 303 See Other, which tells the client to retrieve another URI using GET; 304 Not Modified, which supports caching; 307 Temporary Redirect, which temporarily redirects while preserving the HTTP method and body; and 308 Permanent Redirect, which permanently redirects while preserving the method and body.
In API testing, we should verify the exact redirect status code, the Location header, whether the redirect target works, whether the redirect is temporary or permanent, whether caching behaves correctly for 304, and whether methods are preserved for 307 and 308. Redirect testing is especially important during API migration, endpoint relocation, caching optimization, maintenance routing, and protocol or domain changes.
Key Takeaway
3xx redirection codes are HTTP signals that guide the client to another action. They are not ordinary success responses and they are not automatically failures. They tell the client that a resource moved, another URI should be used, a cached copy is still valid, or a method-preserving redirect is required.
For API testers, the practical rule is clear: do not look only at the final followed response. Inspect the redirect itself when redirect behavior is part of the requirement. Validate the status code, Location header, final target, method behavior, caching rules, and security impact. A correct redirect makes migration and optimization smooth; an incorrect redirect can break clients, hide defects, expose data, or create unstable automation.