diff --git a/api/funkwhale_api/common/middleware.py b/api/funkwhale_api/common/middleware.py
index 96e9c45a667dbda91800c443b08a4b5191c7baa5..59d50b30ead3ea34f5219431475162889461b596 100644
--- a/api/funkwhale_api/common/middleware.py
+++ b/api/funkwhale_api/common/middleware.py
@@ -56,6 +56,10 @@ def serve_spa(request):
 
 
 def get_spa_html(spa_url):
+    if spa_url.startswith("/"):
+        # we try to open a local file
+        with open(spa_url) as f:
+            return f.read()
     cache_key = "spa-html:{}".format(spa_url)
     cached = caches["local"].get(cache_key)
     if cached:
diff --git a/api/tests/common/test_middleware.py b/api/tests/common/test_middleware.py
index 2ed875a53100fb216d09ade2af6fceea3bee4ca1..dd7cd76341fc53571613f94e988899a9ca93352a 100644
--- a/api/tests/common/test_middleware.py
+++ b/api/tests/common/test_middleware.py
@@ -126,6 +126,12 @@ def test_get_spa_html_from_http(local_cache, r_mock, mocker, settings):
     )
 
 
+def test_get_spa_html_from_disk(tmpfile):
+    with open(tmpfile.name, "wb") as f:
+        f.write(b"hello world")
+    assert middleware.get_spa_html(tmpfile.name) == "hello world"
+
+
 def test_get_route_head_tags(mocker, settings):
     match = mocker.Mock(args=[], kwargs={"pk": 42}, func=mocker.Mock())
     resolve = mocker.patch("django.urls.resolve", return_value=match)
diff --git a/changes/changelog.d/705.enhancement b/changes/changelog.d/705.enhancement
new file mode 100644
index 0000000000000000000000000000000000000000..9f25c9cbdb2d3b2410d582d45c52fcd1e0950915
--- /dev/null
+++ b/changes/changelog.d/705.enhancement
@@ -0,0 +1 @@
+Can now use a local file with FUNKWHALE_SPA_HTML_ROOT to avoid sending an HTTP request (#705)