Use "application/octet-stream" as the FileResponse media type fallback#3283
Merged
Kludex merged 1 commit intoMay 23, 2026
Merged
Conversation
When the media type cannot be guessed from the filename or path, FileResponse fell back to text/plain. This causes browsers to render unknown binary files (e.g. .msg) as text instead of downloading them. application/octet-stream is the correct default for unrecognized types per RFC 2046, and matches Django and Werkzeug.
Contributor
There was a problem hiding this comment.
Pull request overview
Updates FileResponse to use a safer default Content-Type when a file’s MIME type cannot be inferred, aligning behavior with common HTTP/MIME expectations and improving browser handling of unknown file types.
Changes:
- Change
FileResponsefallback media type fromtext/plaintoapplication/octet-streamwhenmimetypes.guess_type()cannot determine a type. - Add a regression test asserting the new fallback
Content-Typebehavior.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
starlette/responses.py |
Updates FileResponse default media type fallback to application/octet-stream. |
tests/test_responses.py |
Adds a test covering the unknown-extension fallback Content-Type. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
"application/octet-stream" as the FileResponse media type fallback
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
FileResponsefalls back totext/plainwhen the media type cannot be guessed from the filename or path:For files with an unrecognized extension this means the response is served as
text/plain, so browsers render the bytes inline as text instead of downloading the file. This was reported in discussion #3106 (an Outlook.msgfile rendered as text rather than triggering a download).application/octet-streamis the correct default for unknown content per RFC 2046 ("MIME implementations must at a minimum treat any unrecognized subtypes as being equivalent toapplication/octet-stream") and the MDN guidance. It's also what Django and Werkzeug use:content_type = content_type or "application/octet-stream"send_filefalls back toapplication/octet-streamThe earlier choice of
text/plain(#1027) was made on the assumption that Django usedtext/plain, which isn't the case.This affects
FileResponsedirectly andStaticFiles, which serves files throughFileResponse. Passing an explicitmedia_typeis unchanged.Checklist