Inspect the final response.
In the Network panel, locate the download request. Check its final URL, status, Content-Type and response body. A redirect to a login page can end with a successful HTML response.
If the response begins with an HTML doctype or a sign-in form, the export generator may never have handled the request. Inspect authentication, rewrites and the path sent by the download button.
Use the HAR viewer to inspect a saved recording. Do not share the original recording until you have reviewed it for secrets.
Reject an unexpected representation.
Check status and the expected media type before offering a file. The check below catches HTML, but it cannot establish that the CSV contains the right rows.
const response = await fetch("/api/reports/export");
const type = response.headers.get("content-type") || "";
if (!response.ok || !/^text\/csv(?:;|$)/i.test(type)) {
throw new Error("The server did not return a CSV report");
}
const csv = await response.text();
// Validate the export contract before creating the download.Use your actual documented media type if the endpoint intentionally returns another format. Do not turn a failed response into a downloadable file just because its body exists.
Check the download headers.
Set the correct Content-Type on the file response. Content-Disposition can suggest attachment delivery and a filename; it does not convert HTML into CSV. Inspect it with the Content-Disposition parser.
For a browser cross-origin fetch, exposing the filename header may need Access-Control-Expose-Headers. A navigation download and a scripted fetch are different request contexts.
Test signed-in and expired sessions.
Exercise a valid user, a signed-out user and an expired session. The authorised request should return a usable report. An API denial should produce an explicit error rather than a 200 login page with a CSV filename. Check file structure with the CSV validator, then compare expected records.
References: Content-Disposition and Fetch response handling.