QA How-To
HTTP 404 vs 410: What Testers Need to Know
Compare HTTP status 404 vs 410, learn their caching and SEO effects, and test missing or permanently removed resources with reliable API checks in QA.
20 min read | 3,274 words
TL;DR
404 means the origin has no current representation and makes no promise about permanence. 410 means the resource is intentionally and permanently gone. Testers should verify the product's lifecycle policy, not select a code from the visible error message alone.
Key Takeaways
- Use 404 when the server cannot find a current representation and does not assert that the absence is permanent.
- Use 410 when the resource was intentionally removed and is expected to remain unavailable.
- Test the response status, body contract, headers, authorization behavior, redirects, and repeated requests together.
- Treat soft 404 pages that return 200 as defects because they mislead clients, monitors, and crawlers.
- Verify historical state transitions because a deleted resource can move from 200 to 404, 410, or an archive redirect by policy.
- Keep security-sensitive resources indistinguishable when revealing prior existence would leak information.
The http status 404 vs 410 decision is about what the server knows and is willing to communicate. A 404 Not Found response says that the origin server did not find a current representation for the target resource. A 410 Gone response says that access is no longer available and the condition is expected to be permanent.
For testers, the difference reaches far beyond two status numbers. It affects client retries, cache behavior, link cleanup, observability, search indexing, API contracts, security, and the lifecycle of deleted data. This guide turns that semantic distinction into practical test scenarios you can run at the API and UI layers.
TL;DR
| Question | 404 Not Found | 410 Gone |
|---|---|---|
| Does a current representation exist? | No | No |
| Is permanent removal being asserted? | Not necessarily | Yes |
| Typical case | Unknown route, mistyped ID, hidden resource | Intentionally retired page or deleted public object |
| Should a client keep retrying unchanged? | Usually no, but the resource might appear later | No, unless product policy changes |
| Can it be cached? | Yes, subject to HTTP caching rules and headers | Yes, subject to HTTP caching rules and headers |
| Main QA risk | A real failure is disguised as an ordinary absence | A temporary outage is falsely described as permanent |
A good assertion checks the status code and the business state that caused it. A polished error page is not evidence that the server chose the correct status.
1. HTTP Status 404 vs 410 in Plain English
Both codes are client error responses in the 4xx class, but neither necessarily means the caller made a syntactic mistake. They describe the origin's result when resolving the requested target.
Use 404 when the application cannot find a representation now and either does not know whether the absence is permanent or deliberately avoids saying more. Common examples are a typo in a path, an ID that never existed, a private record hidden from an unauthorized caller, or a resource that might be created later. The same URL can legitimately return 404 today and 200 tomorrow.
Use 410 when the system knows a resource existed, was intentionally withdrawn, and is expected to stay unavailable. A public event page removed after a retention period, a deprecated download deliberately retired without a replacement, or a user-published object erased under a deletion workflow can qualify. The permanence claim is the key.
The codes do not specify the shape of the response body. An API might return Problem Details JSON, while a browser route returns an HTML page. They also do not automatically prove whether a database row exists. The HTTP response expresses the interface's public semantics, which may intentionally conceal storage details.
2. Why the Distinction Matters to QA
Status semantics influence downstream decisions. A mobile client may stop presenting a retry action for 410. A link checker may schedule a later recheck for 404 but remove a 410 URL from its queue. A cache can retain either error response if policy allows it. A crawler may process the stronger removal signal differently from an uncertain absence. Monitoring rules may also exclude expected 404 traffic while alerting on unexpected changes in the 410 rate.
The largest testing risk is semantic drift between teams. A backend developer may use 410 for every soft-deleted database row, while the product owner expects an undo window. A frontend developer may render a custom not-found component for any failed fetch, including a 503 outage. Both screens can look reasonable to a manual tester even though the API contract is wrong.
Include the decision in acceptance criteria. State the resource lifecycle, whether recovery is possible, whether prior existence may be disclosed, and what replacement navigation should appear. Then test from the caller's point of view. If the API promises 410 only after a 30-day recovery window, verify the boundary around that transition rather than checking one permanently seeded example.
For a broader negative-testing model, see API error handling and negative testing.
3. Resource Lifecycle and Expected Transitions
A useful test model treats the status as a state transition, not a static mapping. Consider a public document with draft, published, archived, recoverable-deleted, and purged states. An anonymous request might observe these results:
| Resource state | Plausible response | What to verify |
|---|---|---|
| Draft and private | 404 or 403 by security policy | No existence leak |
| Published | 200 | Correct representation and validators |
| Moved to a replacement | 301 or 308 | Stable Location and no redirect loop |
| Recoverable deletion | 404, or 200 in an owner trash view | Recovery policy is honored |
| Permanently withdrawn | 410 | No restore action and consistent metadata |
| Unknown identifier | 404 | Same safe contract as other unknown IDs |
Build a state table for authenticated owners, other authenticated users, anonymous callers, administrators, and service clients. The result may differ by actor without being inconsistent. An owner could see a tombstone representation while anonymous callers receive 410.
Test temporal boundaries with a controllable clock or seeded timestamps. Avoid waiting in real time for a retention period. Verify the last instant inside the recovery window, the first instant after it, and repeated reads after a background purge. Also test delayed jobs: if the status becomes 410 before physical deletion completes, ensure no endpoint can still expose the content.
Finally, decide whether an identifier can ever be reused. Reusing a URL that once returned 410 for unrelated content can confuse caches and clients, so it deserves an explicit product decision and regression coverage.
4. Response Contract Beyond the Status Code
A robust API assertion covers the response as a coherent contract. Check the media type, stable machine-readable error identifier, human-readable detail, correlation ID, cache directives, and whether the body exposes internal data. A useful JSON error distinguishes code from prose so clients do not parse a translated message.
Problem Details for HTTP APIs commonly uses application/problem+json and fields such as type, title, status, detail, and instance. Extensions can add a trace identifier or domain error code. Do not require every optional field unless the API contract promises it. Do require the numeric body status, when present, to agree with the HTTP status.
For 410, the body can explain that the resource was removed and, when appropriate, link to a replacement. For 404, wording should not falsely claim permanent deletion. In authenticated systems, error details must not reveal the title, owner, deletion time, or prior existence of a protected object.
Also inspect method behavior. A missing resource may return 404 for GET, HEAD, PUT, PATCH, and DELETE, but business policy can differ. An idempotent delete endpoint might return 204 on repeated deletion attempts, while another contract returns 404 or 410. There is no universal rule that replaces the documented contract. The test oracle must come from the API's declared semantics.
5. Caching, Validators, and Stale Errors
404 and 410 responses can be cached. Testers should never assume that an error response bypasses every browser, CDN, reverse proxy, or client cache. The effective behavior depends on HTTP caching rules, response headers, intermediary configuration, and request directives.
Start by capturing Cache-Control, Age, Date, Expires, ETag, and Last-Modified where applicable. Make the same request twice through the production-like path and determine whether the second response came from the origin or a cache. Then change the resource state. A newly created resource should not remain masked by an excessively cached 404. A restored item should not continue returning a stale 410 if restoration is a supported workflow.
Use unique test identifiers when measuring origin behavior, and use a fixed identifier when intentionally testing cache reuse. Record CDN headers only as implementation evidence because vendor-specific header names can change. The contract should focus on observable freshness and invalidation.
Test HEAD as well as GET when supported. It should return status and headers consistent with GET without a response body. Test conditional requests only where validators are defined. A stale client validator for an old 200 representation must not cause a deleted object to be incorrectly reported as 304 Not Modified. State changes should invalidate or supersede old validators according to the system design.
6. Security and Privacy Considerations
Sometimes 404 is chosen even when the server knows that a resource is permanently gone. The reason is information disclosure. Returning 410 only for previously existing account IDs tells an attacker which identifiers were valid. Returning 403 for a private project tells an unauthenticated caller that the project exists. A uniform 404 can intentionally reduce that oracle.
Test the policy with pairs of identifiers: never-created, active but unauthorized, recoverable-deleted, permanently deleted, and malformed but syntactically valid. Compare status, body shape, content length ranges, cache headers, and response timing at a sensible statistical level. Exact timing equality is unrealistic, but obvious deterministic differences deserve investigation.
Do not weaken authorization tests just because the public response is 404. Use privileged setup or database fixtures to prove that the hidden resource exists, then verify that the unauthorized actor cannot read, update, infer, or enumerate it. Check nested routes, search endpoints, export jobs, audit feeds, and attachment URLs. A secure top-level 404 is insufficient if related endpoints reveal the same object.
When deletion is driven by privacy requirements, separate interface semantics from data-erasure proof. A 410 response confirms public unavailability, not physical erasure from backups, analytics stores, or logs. Those controls require their own evidence and retention tests.
7. How to Test 404 and 410 with Playwright
Playwright's API request fixture can validate an HTTP endpoint without opening a browser. The following TypeScript test is runnable in a Playwright project. Set API_BASE_URL to the service under test, and provide stable seeded paths for an unknown resource and a permanently removed resource.
import { test, expect } from '@playwright/test';
const baseURL = process.env.API_BASE_URL ?? 'http://127.0.0.1:3000';
test('unknown resource returns a contract-safe 404', async ({ request }) => {
const response = await request.get(`${baseURL}/api/articles/never-created-qa-fixture`);
expect(response.status()).toBe(404);
expect(response.headers()['content-type']).toContain('application/problem+json');
const problem = await response.json();
expect(problem).toMatchObject({
status: 404,
title: 'Not Found'
});
expect(JSON.stringify(problem)).not.toContain('SELECT');
});
test('retired public resource returns 410 consistently', async ({ request }) => {
const path = `${baseURL}/api/articles/permanently-retired-qa-fixture`;
for (let attempt = 0; attempt < 2; attempt += 1) {
const response = await request.get(path, {
headers: { Accept: 'application/problem+json' }
});
expect(response.status()).toBe(410);
expect(await response.json()).toMatchObject({
status: 410,
title: 'Gone'
});
}
});
Avoid accepting every non-2xx result with a loose assertion such as status >= 400. That assertion cannot detect a gateway outage masquerading as a missing page. Seed the resource state through supported setup APIs or fixtures, not by depending on a random production ID. For more request-fixture techniques, use the Playwright API testing guide.
8. Testing HTTP Status 404 vs 410 in the Browser
End-to-end coverage should verify both network semantics and user recovery. Navigate directly to a missing route, refresh it, open it from an internal link, and use browser history. Confirm that the document request itself returns the expected code. Some single-page applications return the shell with 200 for every route and render a not-found component on the client. That may be acceptable for an internal app, but it is a soft 404 for public crawlable content unless the hosting design supplies the correct document status.
Check the error page for a clear message, a safe route back, keyboard focus, accessible heading structure, page title, and no broken asset requests. A 410 page can offer an archive or replacement without pretending that the old resource still exists. A 404 page can offer search without echoing an untrusted path as raw HTML.
Observe client-side fetch failures separately. If the document loads with 200 but a data request returns 503, the UI must not label the record permanently gone. Exercise offline mode, request timeout, aborted navigation, 401, 403, 404, 410, 429, and 5xx responses so the error mapper cannot collapse unrelated states into one empty-state component.
Verify analytics carefully. Error routes should emit one useful event, not duplicate events on hydration or retries. Do not include sensitive URL fragments or query values in analytics.
9. Redirects, Replacements, and Link Integrity
A removed resource with a clear successor often calls for a redirect rather than 410. Test the product rule, not a blanket preference. If /docs/v1/auth has moved to a direct equivalent, a permanent redirect can preserve bookmarks and integrations. If the old content has no meaningful replacement, redirecting every retired URL to the home page creates confusion and can behave like a soft 404.
For redirects, assert the exact 301 or 308 status chosen by the contract, the Location value, method preservation where relevant, the final response, and the absence of loops. Test absolute and relative URL handling through proxies. Confirm that query parameters are retained only when safe and meaningful.
For 410, scan internal navigation, sitemaps, canonical references, alternate-language links, structured data, feeds, and API discoverability documents. The application should stop generating new links to a deliberately removed resource. External links are not under product control, so the 410 page should remain stable enough to explain the outcome.
For 404, distinguish bad application links from arbitrary user input. A crawler finding an internal 404 has identified a product defect even if the endpoint correctly returns 404. Track source URL, target URL, link element, actor, and environment so the owner can repair it.
10. Observability and Production Diagnostics
Expected client errors can still reveal regressions. Monitor 404 and 410 by normalized route template, caller type, deployment version, region, and referrer category. Never use unbounded raw IDs as metric labels. A sudden 404 increase on /api/orders/{id} after a routing release is materially different from internet noise against unknown paths.
Create separate signals for expected and unexpected outcomes. A known retired campaign can generate routine 410 traffic without paging anyone. An active product page switching from 200 to 410 should fail a synthetic check immediately. A spike in 404 after cache invalidation may indicate inconsistent deployment across origins.
Logs should include a correlation identifier, resolved route, public error code, relevant lifecycle state, and safe actor classification. They should not include access tokens, full private payloads, or database error dumps. Trace the request through CDN, gateway, application, and backing service when the observed code could have been rewritten along the path.
During incident review, ask where the code originated. A framework router, API gateway, application handler, object store, and security layer can all produce 404. Only one may know the business lifecycle. This origin analysis prevents teams from treating all identical status numbers as the same defect.
11. A Practical Test Matrix for Deleted Resources
Organize tests across state, actor, method, cache path, and time. Start with a small pairwise set, then add high-risk combinations. Useful scenarios include:
- A never-created valid ID returns the safe 404 contract.
- An active public ID returns 200, then follows the documented deletion transition.
- A recoverable-deleted item remains restorable and does not claim irreversible removal.
- A purged public item returns 410 when policy permits disclosing prior existence.
- An unauthorized active item is indistinguishable from an unknown item when concealment is required.
- Repeated
GETandHEADrequests remain consistent through cache layers. - A stale conditional request cannot recover deleted content or yield an incorrect 304.
- Internal search, sitemap, and navigation stop advertising the removed URL.
- A replacement redirect preserves the intended destination and does not land on a generic page.
- Concurrent restore and delete operations resolve to a documented final state.
Add contract tests for each consumer that branches on 404 or 410. A generated OpenAPI client may expose both through the same exception type, so verify the raw status remains available. If deletion commands are retried, review API idempotency testing to cover duplicate requests and race conditions.
12. HTTP Status 404 vs 410 Release Checklist
Before release, confirm that the API specification documents both codes where they can occur and gives representative response bodies. Verify that frontend copy reflects uncertainty for 404 and permanence for 410. Confirm cache freshness and invalidation with the production-like CDN or reverse proxy configuration.
Run contract, integration, browser, accessibility, link, and monitoring checks. Include rollback behavior. If an application version starts returning 410 and must be rolled back, old caches must not trap users in the permanent response. Review dashboards for route normalization and confirm expected errors do not overwhelm alerts.
Ask the final product questions: Can the item return? May we disclose that it existed? Is there an exact replacement? Should clients remove local references? Which actor sees which result? If those answers are not written down, the status assertion is based on guesswork.
The best release evidence combines a lifecycle state table, automated API checks, browser screenshots or accessibility results where useful, cache observations, and a trace showing which layer generated the response. This makes the decision reviewable rather than dependent on one tester's interpretation.
Interview Questions and Answers
Q: What is the main difference between 404 and 410?
404 reports that no current representation was found without asserting permanence. 410 explicitly reports that access is gone and the condition is expected to be permanent. I would choose between them from the product lifecycle and disclosure policy, not from whether a database row once existed.
Q: Can 404 and 410 responses be cached?
Yes. Error status does not automatically disable caching. I inspect HTTP caching headers, intermediary behavior, repeated responses, and invalidation when a resource is created or restored.
Q: What is a soft 404?
A soft 404 is a page that looks like a not-found result but returns a success status, commonly 200. It can mislead clients, synthetic monitors, analytics, and crawlers. I verify the document response in the network layer, not only the rendered message.
Q: Why might a service return 404 for a deleted private resource instead of 410?
It may need to hide whether the identifier ever existed. A different response for valid, unauthorized, or deleted IDs can become an enumeration oracle. I test the uniform public behavior while independently proving authorization with controlled fixtures.
Q: Should repeated DELETE return 404, 410, or 204?
Any of those can be part of a defensible contract. An idempotent operation means repeated requests have the same intended effect, not necessarily the same status. I assert the documented response and confirm that no repeated side effect occurs.
Q: How would you test a 404-to-410 transition?
I would seed a resource, delete it, control the retention clock, and verify boundary states before and after permanent withdrawal. I would include owner and anonymous actors, cache invalidation, GET and HEAD, stale validators, restore races, and downstream links.
Q: Is 410 always better for SEO after a page is deleted?
No universal status choice should be made only for SEO. The response must tell the truth about permanence, replacements, and product policy. I also verify sitemaps, internal links, canonical data, and redirects because status alone does not repair site hygiene.
Common Mistakes
- Checking only the error text and missing a 200 soft 404 or a 503 rendered as not found.
- Returning 410 for a recoverable item, which makes a temporary product state look permanent.
- Assuming all 404 responses come from application business logic instead of tracing the router, gateway, cache, and origin.
- Disclosing prior existence through 410, response size, or timing on security-sensitive identifiers.
- Ignoring
HEAD, repeated requests, stale validators, and cache invalidation. - Redirecting every removed URL to the home page even when there is no equivalent replacement.
- Using random production IDs as fixtures, which makes expected state unverifiable and tests flaky.
- Treating a correct 404 on an internally linked URL as a passing product experience.
Conclusion
The practical answer to http status 404 vs 410 is simple: 404 communicates present absence without a permanence promise, while 410 communicates intentional, expected permanent removal. The difficult part is proving that the resource lifecycle, disclosure policy, cache behavior, UI, and downstream consumers all agree with that meaning.
Create a state-by-actor table, seed deterministic resources, automate status and contract checks, and verify the full delivery path. That evidence turns two easily confused codes into a reliable, testable API promise.
Interview Questions and Answers
Explain HTTP 404 vs 410 in one minute.
404 means no current representation was found, without claiming that the absence is permanent. 410 is a stronger statement that access has been intentionally removed and is expected to stay unavailable. I select the code from lifecycle and security policy, then test status, body, headers, actors, caches, and transitions.
How would you test caching of a 404 response?
I would request a unique missing URL through the production-like cache path, record cache headers, and repeat the request. Then I would create the resource or change its fixture state and verify that invalidation prevents the old 404 from masking the new 200 response. I would distinguish origin results from intermediary results using traces and safe diagnostic headers.
Why is UI text insufficient when testing not-found behavior?
A frontend can render the same not-found component for 404, 410, timeouts, and 5xx failures. A single-page application can also return 200 for its document while displaying a missing-page message. I inspect both the document and data requests, then verify accessible recovery behavior.
How can 410 create a security issue?
If only formerly valid identifiers return 410, an attacker can distinguish them from never-created IDs that return 404. The status, body size, cache headers, or timing can expose prior existence. For sensitive objects, I test that the public contract is intentionally uniform across those states.
What tests belong in a deleted-resource matrix?
I cover active, unknown, unauthorized, recoverable-deleted, permanently removed, restored, and replaced states. I cross those with actors, methods, cache paths, and time boundaries. I also verify nested endpoints, search, exports, sitemaps, redirects, and concurrent delete or restore actions.
Does idempotent DELETE require the same response status every time?
No. Idempotency concerns the intended server effect, not strict equality of every response. A contract may return 204 first and 404 or 410 later, but it must document that behavior and prevent duplicate side effects.
When should a removed URL redirect instead of returning 410?
A permanent redirect is usually appropriate when there is a direct, meaningful successor. If no equivalent exists and removal is permanent, 410 can be more truthful. I test the exact status, Location header, method handling, final destination, link updates, and redirect loops.
Frequently Asked Questions
What is the difference between HTTP 404 and 410?
404 means the server did not find a current representation and does not assert that the condition is permanent. 410 means the resource is gone and the server expects that condition to be permanent.
Should a deleted API resource return 404 or 410?
Use the documented lifecycle policy. A recoverable or deliberately concealed resource often returns 404, while an intentionally and permanently withdrawn public resource may return 410.
Can a 404 response be cached?
Yes. HTTP errors are not automatically uncacheable. Test the response headers and every relevant intermediary, then verify invalidation when the resource becomes available.
Can a 410 response later become 200?
It is technically possible, but it contradicts the permanence communicated by 410 and can produce stale client or cache behavior. If restoration is supported, 404 or a tombstone representation may express the temporary state more accurately.
What is a soft 404 in testing?
A soft 404 occurs when the UI says content is missing but the document returns a success status such as 200. Testers should inspect the actual network response because visual copy alone cannot prove HTTP semantics.
Should an unknown private resource return 403 or 404?
Many systems use 404 to avoid confirming that a protected identifier exists. The correct choice depends on the security contract, and all related endpoints should follow the same concealment policy.
How do I automate 404 and 410 API tests?
Seed deterministic never-created, recoverable-deleted, and permanently removed resources. Assert the exact status, error schema, headers, actor-specific behavior, repeated requests, and cache transitions with an API-capable framework such as Playwright.