diff --git a/api/funkwhale_api/federation/serializers.py b/api/funkwhale_api/federation/serializers.py
index 942892a95c6e23e34b33fab3fb5db64096f4de9e..6305bd073e231ae65bb675404b9234c3386d9530 100644
--- a/api/funkwhale_api/federation/serializers.py
+++ b/api/funkwhale_api/federation/serializers.py
@@ -1159,7 +1159,7 @@ class UploadSerializer(jsonld.JsonLdSerializer):
             "duration": instance.duration,
             "url": [
                 {
-                    "href": utils.full_url(instance.listen_url),
+                    "href": utils.full_url(instance.listen_url_no_download),
                     "type": "Link",
                     "mediaType": instance.mimetype,
                 },
@@ -1235,7 +1235,7 @@ class ChannelUploadSerializer(serializers.Serializer):
                 {
                     "type": "Link",
                     "mimeType": upload.mimetype,
-                    "href": utils.full_url(upload.listen_url),
+                    "href": utils.full_url(upload.listen_url_no_download),
                 },
                 {
                     "type": "Link",
diff --git a/api/funkwhale_api/music/models.py b/api/funkwhale_api/music/models.py
index 9f627d47c1e1babfe47f1870107d6ec775bdf814..f53e8e463e7d198ada7590231b8f77275b55252a 100644
--- a/api/funkwhale_api/music/models.py
+++ b/api/funkwhale_api/music/models.py
@@ -846,6 +846,11 @@ class Upload(models.Model):
     def listen_url(self):
         return self.track.listen_url + "?upload={}".format(self.uuid)
 
+    @property
+    def listen_url_no_download(self):
+        # Not using reverse because this is slow
+        return self.listen_url + "&download=false"
+
     def get_transcoded_version(self, format, max_bitrate=None):
         if format:
             mimetype = utils.EXTENSION_TO_MIMETYPE[format]
diff --git a/api/funkwhale_api/music/views.py b/api/funkwhale_api/music/views.py
index 79727cd7d974cdc5bc0b7502a0ec25a9b9abb361..57d009e99a586bcb3d21c92dbd65c957657720a0 100644
--- a/api/funkwhale_api/music/views.py
+++ b/api/funkwhale_api/music/views.py
@@ -393,7 +393,9 @@ def get_content_disposition(filename):
     return "attachment; {}".format(filename)
 
 
-def handle_serve(upload, user, format=None, max_bitrate=None, proxy_media=True):
+def handle_serve(
+    upload, user, format=None, max_bitrate=None, proxy_media=True, download=True
+):
     f = upload
     # we update the accessed_date
     now = timezone.now()
@@ -450,7 +452,8 @@ def handle_serve(upload, user, format=None, max_bitrate=None, proxy_media=True):
     mapping = {"nginx": "X-Accel-Redirect", "apache2": "X-Sendfile"}
     file_header = mapping[settings.REVERSE_PROXY_TYPE]
     response[file_header] = file_path
-    response["Content-Disposition"] = get_content_disposition(filename)
+    if download:
+        response["Content-Disposition"] = get_content_disposition(filename)
     if mt:
         response["Content-Type"] = mt
 
@@ -476,6 +479,7 @@ class ListenViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
             "track__album__artist", "track__artist"
         )
         explicit_file = request.GET.get("upload")
+        download = request.GET.get("download", "true").lower() == "true"
         if explicit_file:
             queryset = queryset.filter(uuid=explicit_file)
         queryset = queryset.playable_by(actor)
@@ -499,6 +503,7 @@ class ListenViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
             format=format,
             max_bitrate=max_bitrate,
             proxy_media=settings.PROXY_MEDIA,
+            download=download,
         )
 
 
diff --git a/api/tests/federation/test_serializers.py b/api/tests/federation/test_serializers.py
index 60898c7765e3d647531118f605c780de052a669f..4076fdd5a1ca853d74d7a1b3f5881a1bda221582 100644
--- a/api/tests/federation/test_serializers.py
+++ b/api/tests/federation/test_serializers.py
@@ -953,7 +953,7 @@ def test_activity_pub_audio_serializer_to_ap(factories):
         "attributedTo": upload.library.actor.fid,
         "url": [
             {
-                "href": utils.full_url(upload.listen_url),
+                "href": utils.full_url(upload.listen_url_no_download),
                 "type": "Link",
                 "mediaType": "audio/mp3",
             },
@@ -1105,7 +1105,7 @@ def test_channel_upload_serializer(factories):
             {
                 "type": "Link",
                 "mimeType": upload.mimetype,
-                "href": utils.full_url(upload.listen_url),
+                "href": utils.full_url(upload.listen_url_no_download),
             },
             {
                 "type": "Link",
diff --git a/api/tests/music/test_models.py b/api/tests/music/test_models.py
index c723b0104a77f717d9098ad3d146a4b8c2e7e2d3..d8022c9646f7419e4c39ebe4f926b6dd7122c0ac 100644
--- a/api/tests/music/test_models.py
+++ b/api/tests/music/test_models.py
@@ -437,6 +437,13 @@ def test_upload_listen_url(factories):
     assert upload.listen_url == expected
 
 
+def test_upload_listen_url_no_download(factories):
+    upload = factories["music.Upload"]()
+    expected = upload.track.listen_url + "?upload={}&download=false".format(upload.uuid)
+
+    assert upload.listen_url_no_download == expected
+
+
 def test_library_schedule_scan(factories, now, mocker):
     on_commit = mocker.patch("funkwhale_api.common.utils.on_commit")
     library = factories["music.Library"](uploads_count=5)
diff --git a/api/tests/music/test_views.py b/api/tests/music/test_views.py
index 6f962ff070338ea64de32dfaa940fdad645d7e85..c56aeee66d23bb75ce5bf3097410b76e5be13df0 100644
--- a/api/tests/music/test_views.py
+++ b/api/tests/music/test_views.py
@@ -382,10 +382,28 @@ def test_listen_correct_access(factories, logged_in_api_client):
         library__privacy_level="me",
         import_status="finished",
     )
+    expected_filename = upload.track.full_name + ".ogg"
     url = reverse("api:v1:listen-detail", kwargs={"uuid": upload.track.uuid})
     response = logged_in_api_client.get(url)
 
     assert response.status_code == 200
+    assert response["Content-Disposition"] == "attachment; filename*=UTF-8''{}".format(
+        urllib.parse.quote(expected_filename)
+    )
+
+
+def test_listen_correct_access_download_false(factories, logged_in_api_client):
+    logged_in_api_client.user.create_actor()
+    upload = factories["music.Upload"](
+        library__actor=logged_in_api_client.user.actor,
+        library__privacy_level="me",
+        import_status="finished",
+    )
+    url = reverse("api:v1:listen-detail", kwargs={"uuid": upload.track.uuid})
+    response = logged_in_api_client.get(url, {"download": "false"})
+
+    assert response.status_code == 200
+    assert "Content-Disposition" not in response
 
 
 def test_listen_explicit_file(factories, logged_in_api_client, mocker, settings):
@@ -406,6 +424,7 @@ def test_listen_explicit_file(factories, logged_in_api_client, mocker, settings)
         format=None,
         max_bitrate=None,
         proxy_media=settings.PROXY_MEDIA,
+        download=True,
     )
 
 
@@ -500,6 +519,7 @@ def test_listen_transcode(factories, now, logged_in_api_client, mocker, settings
         format="mp3",
         max_bitrate=None,
         proxy_media=settings.PROXY_MEDIA,
+        download=True,
     )
 
 
@@ -532,6 +552,7 @@ def test_listen_transcode_bitrate(
         format=None,
         max_bitrate=expected,
         proxy_media=settings.PROXY_MEDIA,
+        download=True,
     )
 
 
@@ -562,6 +583,7 @@ def test_listen_transcode_in_place(
         format="mp3",
         max_bitrate=None,
         proxy_media=settings.PROXY_MEDIA,
+        download=True,
     )