diff --git a/assets/src/bundles/webapp/iframes.js b/assets/src/bundles/browse/iframe.js
rename from assets/src/bundles/webapp/iframes.js
rename to assets/src/bundles/browse/iframe.js
--- a/assets/src/bundles/webapp/iframes.js
+++ b/assets/src/bundles/browse/iframe.js
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2021  The Software Heritage developers
+ * Copyright (C) 2021-2022  The Software Heritage developers
  * See the AUTHORS file at the top-level directory of this distribution
  * License: GNU Affero General Public License version 3, or any later version
  * See top-level LICENSE file for more information
@@ -13,10 +13,10 @@
       to do so.
     </p>
     <pre><code class="swh-iframe-html html">&lt;iframe style="width: 100%; height: 500px; border: 1px solid rgba(0, 0, 0, 0.125);"
-        src="${window.location.origin}${Urls.swhid_iframe(objectSWHID.replaceAll('\n', ''))}"&gt;
+        src="${window.location.origin}${Urls.browse_swhid_iframe(objectSWHID.replaceAll('\n', ''))}"&gt;
 &lt;/iframe&gt;</code></pre>
     <iframe style="width: 100%; height: 500px; border: 1px solid rgba(0, 0, 0, 0.125);"
-            src="${window.location.origin}${Urls.swhid_iframe(objectSWHID.replaceAll('\n', ''))}">
+            src="${window.location.origin}${Urls.browse_swhid_iframe(objectSWHID.replaceAll('\n', ''))}">
     </iframe>`;
   swh.webapp.showModalHtml(`Software Heritage ${objectType} iframe`, html, '1000px');
   swh.webapp.highlightCode(false, '.swh-iframe-html');
diff --git a/assets/src/bundles/browse/index.js b/assets/src/bundles/browse/index.js
--- a/assets/src/bundles/browse/index.js
+++ b/assets/src/bundles/browse/index.js
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2018  The Software Heritage developers
+ * Copyright (C) 2018-2022  The Software Heritage developers
  * See the AUTHORS file at the top-level directory of this distribution
  * License: GNU Affero General Public License version 3, or any later version
  * See top-level LICENSE file for more information
@@ -7,12 +7,13 @@
 
 // main bundle for the swh-web/browse application
 
-import './browse.css';
 import './breadcrumbs.css';
+import './browse.css';
 import './content.css';
 import './snapshot-navigation.css';
 
-export * from './snapshot-navigation';
-export * from './origin-search';
 export * from './browse-utils';
+export * from './iframe';
+export * from './origin-search';
+export * from './snapshot-navigation';
 export * from './swhid-utils';
diff --git a/assets/src/bundles/webapp/index.js b/assets/src/bundles/webapp/index.js
--- a/assets/src/bundles/webapp/index.js
+++ b/assets/src/bundles/webapp/index.js
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) 2018-2021  The Software Heritage developers
+ * Copyright (C) 2018-2022  The Software Heritage developers
  * See the AUTHORS file at the top-level directory of this distribution
  * License: GNU Affero General Public License version 3, or any later version
  * See top-level LICENSE file for more information
@@ -9,21 +9,19 @@
 // and utility js modules used in all swh-web applications
 
 // global swh-web custom stylesheets
-import './webapp.css';
 import './breadcrumbs.css';
 import './coverage.css';
-
-export * from './webapp-utils';
+import './webapp.css';
 
 // utility js modules
+export * from './badges';
 export * from './code-highlighting';
-export * from './readme-rendering';
-export * from './pdf-rendering';
-export * from './notebook-rendering';
-export * from './xss-filtering';
 export * from './history-counters';
-export * from './badges';
-export * from './sentry';
 export * from './math-typesetting';
+export * from './notebook-rendering';
+export * from './pdf-rendering';
+export * from './readme-rendering';
+export * from './sentry';
 export * from './status-widget';
-export * from './iframes';
+export * from './webapp-utils';
+export * from './xss-filtering';
diff --git a/swh/web/templates/misc/iframe.html b/swh/web/browse/templates/browse-iframe.html
rename from swh/web/templates/misc/iframe.html
rename to swh/web/browse/templates/browse-iframe.html
--- a/swh/web/templates/misc/iframe.html
+++ b/swh/web/browse/templates/browse-iframe.html
@@ -1,5 +1,5 @@
 {% comment %}
-Copyright (C) 2021  The Software Heritage developers
+Copyright (C) 2021-2022  The Software Heritage developers
 See the AUTHORS file at the top-level directory of this distribution
 License: GNU Affero General Public License version 3, or any later version
 See top-level LICENSE file for more information
@@ -25,7 +25,7 @@
 /*
 @licstart  The following is the entire license notice for the JavaScript code in this page.
 
-Copyright (C) 2021  The Software Heritage developers
+Copyright (C) 2021-2022  The Software Heritage developers
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Affero General Public License as
@@ -129,7 +129,7 @@
                 </div>
                 <div class="ml-auto d-flex align-items-center">
                   {% if swhid != focus_swhid %}
-                    <a class="d-flex align-items-center pr-2" href="{% url 'swhid-iframe' focus_swhid %}"
+                    <a class="d-flex align-items-center pr-2" href="{% url 'browse-swhid-iframe' focus_swhid %}"
                         title="Reset view to its original state">
                       <div class="d-none d-lg-block">Reset view</div>
                       <i class="mdi mdi-refresh" aria-hidden="true"></i>
diff --git a/swh/web/browse/templates/includes/show-swhids.html b/swh/web/browse/templates/includes/show-swhids.html
--- a/swh/web/browse/templates/includes/show-swhids.html
+++ b/swh/web/browse/templates/includes/show-swhids.html
@@ -1,5 +1,5 @@
 {% comment %}
-Copyright (C) 2017-2021  The Software Heritage developers
+Copyright (C) 2017-2022  The Software Heritage developers
 See the AUTHORS file at the top-level directory of this distribution
 License: GNU Affero General Public License version 3, or any later version
 See top-level LICENSE file for more information
@@ -77,7 +77,7 @@
                     {% endif %}
                     {% if swhid_info.object_type.name.lower == "content" or swhid_info.object_type.name.lower == "directory" %}
                       <a class="float-right" style="cursor: pointer;"
-                         onclick="swh.webapp.showIframeInfoModal('{{ swhid_info.object_type.name.lower }}', $(this).parent().parent().find('.swhid').text())">
+                         onclick="swh.browse.showIframeInfoModal('{{ swhid_info.object_type.name.lower }}', $(this).parent().parent().find('.swhid').text())">
                         Iframe embedding
                       </a>
                     {% endif %}
diff --git a/swh/web/browse/urls.py b/swh/web/browse/urls.py
--- a/swh/web/browse/urls.py
+++ b/swh/web/browse/urls.py
@@ -11,6 +11,7 @@
 from swh.web.browse.identifiers import swhid_browse
 import swh.web.browse.views.content  # noqa
 import swh.web.browse.views.directory  # noqa
+import swh.web.browse.views.iframe  # noqa
 import swh.web.browse.views.origin  # noqa
 import swh.web.browse.views.release  # noqa
 import swh.web.browse.views.revision  # noqa
@@ -47,6 +48,10 @@
     return redirect(reverse("origin-save"))
 
 
+def _browse_swhid_iframe_legacy(request: HttpRequest, swhid: str) -> HttpResponse:
+    return redirect(reverse("browse-swhid-iframe", url_args={"swhid": swhid}))
+
+
 urlpatterns = [
     url(r"^browse/$", _browse_search_view),
     url(r"^browse/help/$", _browse_help_view, name="browse-help"),
@@ -59,6 +64,11 @@
         swhid_browse,
         name="browse-swhid-legacy",
     ),
+    url(
+        r"^embed/(?P<swhid>swh:[0-9]+:[a-z]+:[0-9a-f]+.*)/$",
+        _browse_swhid_iframe_legacy,
+        name="browse-swhid-iframe-legacy",
+    ),
 ]
 
 urlpatterns += BrowseUrls.get_url_patterns()
diff --git a/swh/web/misc/iframe.py b/swh/web/browse/views/iframe.py
rename from swh/web/misc/iframe.py
rename to swh/web/browse/views/iframe.py
--- a/swh/web/misc/iframe.py
+++ b/swh/web/browse/views/iframe.py
@@ -11,6 +11,7 @@
 
 from swh.model.hashutil import hash_to_bytes
 from swh.model.swhids import CoreSWHID, ObjectType, QualifiedSWHID
+from swh.web.browse.browseurls import browse_route
 from swh.web.browse.snapshot_context import get_snapshot_context
 from swh.web.browse.utils import (
     content_display_max_size,
@@ -67,7 +68,7 @@
                 path=(path or "/") + d["name"] + "/",
             )
             d["url"] = reverse(
-                "swhid-iframe",
+                "browse-swhid-iframe",
                 url_args={"swhid": str(dir_swhid)},
                 query_params={"focus_swhid": str(focus_swhid)},
             )
@@ -84,7 +85,7 @@
             lines=(focus_swhid.lines if object_id == focus_swhid.object_id else None),
         )
         f["url"] = reverse(
-            "swhid-iframe",
+            "browse-swhid-iframe",
             url_args={"swhid": str(cnt_swhid)},
             query_params={"focus_swhid": str(focus_swhid)},
         )
@@ -135,7 +136,7 @@
                 "object_id": root_dir_swhid.object_id.hex(),
                 "path": "/",
                 "url": reverse(
-                    "swhid-iframe",
+                    "browse-swhid-iframe",
                     url_args={"swhid": str(root_dir_swhid)},
                     query_params={
                         "focus_swhid": str(focus_swhid)
@@ -162,7 +163,7 @@
                     "object_id": dir_swhid.object_id.hex(),
                     "path": dir_swhid.path.decode("utf-8") if dir_swhid.path else "",
                     "url": reverse(
-                        "swhid-iframe",
+                        "browse-swhid-iframe",
                         url_args={"swhid": str(dir_swhid)},
                         query_params={"focus_swhid": str(focus_swhid)},
                     ),
@@ -181,6 +182,10 @@
     return breadcrumbs, root_dir
 
 
+@browse_route(
+    r"embed/(?P<swhid>swh:[0-9]+:[a-z]+:[0-9a-f]+.*)/",
+    view_name="browse-swhid-iframe",
+)
 @xframe_options_exempt
 def swhid_iframe(request, swhid: str):
     """Django view that can be embedded in an iframe to display objects archived
@@ -308,7 +313,7 @@
 
     return render(
         request,
-        "misc/iframe.html",
+        "browse-iframe.html",
         {
             **view_data,
             "iframe_mode": True,
@@ -334,6 +339,6 @@
     url(
         r"^embed/(?P<swhid>swh:[0-9]+:[a-z]+:[0-9a-f]+.*)/$",
         swhid_iframe,
-        name="swhid-iframe",
+        name="browse-swhid-iframe",
     ),
 ]
diff --git a/swh/web/misc/urls.py b/swh/web/misc/urls.py
--- a/swh/web/misc/urls.py
+++ b/swh/web/misc/urls.py
@@ -66,7 +66,6 @@
     url(r"^stat_counters/$", _stat_counters, name="stat-counters"),
     url(r"^", include("swh.web.misc.badges")),
     url(r"^metrics/prometheus/$", prometheus_metrics, name="metrics-prometheus"),
-    url(r"^", include("swh.web.misc.iframe")),
     url(r"^", include("swh.web.misc.fundraising")),
     url(r"^hiring/banner/$", hiring_banner, name="swh-hiring-banner"),
 ]
diff --git a/swh/web/tests/misc/test_iframe.py b/swh/web/tests/browse/views/test_iframe.py
rename from swh/web/tests/misc/test_iframe.py
rename to swh/web/tests/browse/views/test_iframe.py
--- a/swh/web/tests/misc/test_iframe.py
+++ b/swh/web/tests/browse/views/test_iframe.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2021  The Software Heritage developers
+# Copyright (C) 2021-2022  The Software Heritage developers
 # See the AUTHORS file at the top-level directory of this distribution
 # License: GNU Affero General Public License version 3, or any later version
 # See top-level LICENSE file for more information
@@ -13,9 +13,9 @@
 
 
 def test_content_swhid_iframe(client, content_swhid):
-    url = reverse("swhid-iframe", url_args={"swhid": str(content_swhid)})
+    url = reverse("browse-swhid-iframe", url_args={"swhid": str(content_swhid)})
     check_html_get_response(
-        client, url, status_code=200, template_used="misc/iframe.html"
+        client, url, status_code=200, template_used="browse-iframe.html"
     )
 
 
@@ -23,16 +23,16 @@
     content_core_swhid = CoreSWHID(
         object_type=content_swhid.object_type, object_id=content_swhid.object_id
     )
-    url = reverse("swhid-iframe", url_args={"swhid": str(content_core_swhid)})
+    url = reverse("browse-swhid-iframe", url_args={"swhid": str(content_core_swhid)})
     check_html_get_response(
-        client, url, status_code=200, template_used="misc/iframe.html"
+        client, url, status_code=200, template_used="browse-iframe.html"
     )
 
 
 def test_directory_swhid_iframe(client, directory_swhid):
-    url = reverse("swhid-iframe", url_args={"swhid": str(directory_swhid)})
+    url = reverse("browse-swhid-iframe", url_args={"swhid": str(directory_swhid)})
     check_html_get_response(
-        client, url, status_code=200, template_used="misc/iframe.html"
+        client, url, status_code=200, template_used="browse-iframe.html"
     )
 
 
@@ -40,16 +40,16 @@
     directory_core_swhid = CoreSWHID(
         object_type=directory_swhid.object_type, object_id=directory_swhid.object_id
     )
-    url = reverse("swhid-iframe", url_args={"swhid": str(directory_core_swhid)})
+    url = reverse("browse-swhid-iframe", url_args={"swhid": str(directory_core_swhid)})
     check_html_get_response(
-        client, url, status_code=200, template_used="misc/iframe.html"
+        client, url, status_code=200, template_used="browse-iframe.html"
     )
 
 
 def test_iframe_unsupported_object(client, revision_swhid):
-    url = reverse("swhid-iframe", url_args={"swhid": str(revision_swhid)})
+    url = reverse("browse-swhid-iframe", url_args={"swhid": str(revision_swhid)})
     check_html_get_response(
-        client, url, status_code=400, template_used="misc/iframe.html"
+        client, url, status_code=400, template_used="browse-iframe.html"
     )
 
 
@@ -57,17 +57,19 @@
     swhid = CoreSWHID(
         object_type=ObjectType.DIRECTORY, object_id=hash_to_bytes(unknown_directory)
     )
-    url = reverse("swhid-iframe", url_args={"swhid": str(swhid)})
+    url = reverse("browse-swhid-iframe", url_args={"swhid": str(swhid)})
     check_html_get_response(
-        client, url, status_code=404, template_used="misc/iframe.html"
+        client, url, status_code=404, template_used="browse-iframe.html"
     )
 
 
 def test_swhid_iframe_unknown_error(client, mocker, content_swhid):
-    mocker.patch("swh.web.misc.iframe.get_swhid").side_effect = Exception("Error")
-    url = reverse("swhid-iframe", url_args={"swhid": str(content_swhid)})
+    mocker.patch("swh.web.browse.views.iframe.get_swhid").side_effect = Exception(
+        "Error"
+    )
+    url = reverse("browse-swhid-iframe", url_args={"swhid": str(content_swhid)})
     check_html_get_response(
-        client, url, status_code=500, template_used="misc/iframe.html"
+        client, url, status_code=500, template_used="browse-iframe.html"
     )
 
 
@@ -93,14 +95,32 @@
     )
 
     url = reverse(
-        "swhid-iframe",
+        "browse-swhid-iframe",
         url_args={"swhid": f"{str(swhid)};path={path}"},
         query_params={"focus_swhid": str(root_swhid)},
     )
     resp = check_html_get_response(
-        client, url, status_code=200, template_used="misc/iframe.html"
+        client, url, status_code=200, template_used="browse-iframe.html"
     )
 
     archive_url = reverse("browse-swhid", url_args={"swhid": str(qualified_swhid)})
 
     assert_contains(resp, archive_url)
+
+
+def test_iframe_legacy_url_redirection(client, directory_swhid):
+    directory_core_swhid = CoreSWHID(
+        object_type=directory_swhid.object_type, object_id=directory_swhid.object_id
+    )
+    url = reverse(
+        "browse-swhid-iframe-legacy", url_args={"swhid": str(directory_core_swhid)}
+    )
+    resp = check_html_get_response(
+        client,
+        url,
+        status_code=302,
+    )
+
+    assert resp["Location"] == reverse(
+        "browse-swhid-iframe", url_args={"swhid": str(directory_core_swhid)}
+    )