diff --git a/src/core/frontend/applets/web_browser.cpp b/src/core/frontend/applets/web_browser.cpp
index a5d8f82ac..50db6a654 100644
--- a/src/core/frontend/applets/web_browser.cpp
+++ b/src/core/frontend/applets/web_browser.cpp
@@ -20,4 +20,13 @@ void DefaultWebBrowserApplet::OpenLocalWebPage(
     callback(Service::AM::Applets::WebExitReason::WindowClosed, "http://localhost/");
 }
 
+void DefaultWebBrowserApplet::OpenExternalWebPage(
+    std::string_view external_url,
+    std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const {
+    LOG_WARNING(Service_AM, "(STUBBED) called, backend requested to open external web page at {}",
+                external_url);
+
+    callback(Service::AM::Applets::WebExitReason::WindowClosed, "http://localhost/");
+}
+
 } // namespace Core::Frontend
diff --git a/src/core/frontend/applets/web_browser.h b/src/core/frontend/applets/web_browser.h
index 5b0629cfb..1c5ef19a9 100644
--- a/src/core/frontend/applets/web_browser.h
+++ b/src/core/frontend/applets/web_browser.h
@@ -18,6 +18,10 @@ public:
     virtual void OpenLocalWebPage(
         std::string_view local_url, std::function<void()> extract_romfs_callback,
         std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const = 0;
+
+    virtual void OpenExternalWebPage(
+        std::string_view external_url,
+        std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const = 0;
 };
 
 class DefaultWebBrowserApplet final : public WebBrowserApplet {
@@ -27,6 +31,10 @@ public:
     void OpenLocalWebPage(std::string_view local_url, std::function<void()> extract_romfs_callback,
                           std::function<void(Service::AM::Applets::WebExitReason, std::string)>
                               callback) const override;
+
+    void OpenExternalWebPage(std::string_view external_url,
+                             std::function<void(Service::AM::Applets::WebExitReason, std::string)>
+                                 callback) const override;
 };
 
 } // namespace Core::Frontend
diff --git a/src/core/hle/service/am/applets/web_browser.cpp b/src/core/hle/service/am/applets/web_browser.cpp
index 9c8be156f..2ab420789 100644
--- a/src/core/hle/service/am/applets/web_browser.cpp
+++ b/src/core/hle/service/am/applets/web_browser.cpp
@@ -409,7 +409,9 @@ void WebBrowser::InitializeOffline() {
 
 void WebBrowser::InitializeShare() {}
 
-void WebBrowser::InitializeWeb() {}
+void WebBrowser::InitializeWeb() {
+    external_url = ParseStringValue(GetInputTLVData(WebArgInputTLVType::InitialURL).value());
+}
 
 void WebBrowser::InitializeWifi() {}
 
@@ -456,8 +458,12 @@ void WebBrowser::ExecuteShare() {
 }
 
 void WebBrowser::ExecuteWeb() {
-    LOG_WARNING(Service_AM, "(STUBBED) called, Web Applet is not implemented");
-    WebBrowserExit(WebExitReason::EndButtonPressed);
+    LOG_INFO(Service_AM, "Opening external URL at {}", external_url);
+
+    frontend.OpenExternalWebPage(external_url,
+                                 [this](WebExitReason exit_reason, std::string last_url) {
+                                     WebBrowserExit(exit_reason, last_url);
+                                 });
 }
 
 void WebBrowser::ExecuteWifi() {
diff --git a/src/core/hle/service/am/applets/web_browser.h b/src/core/hle/service/am/applets/web_browser.h
index 936a49a86..04c274754 100644
--- a/src/core/hle/service/am/applets/web_browser.h
+++ b/src/core/hle/service/am/applets/web_browser.h
@@ -79,6 +79,8 @@ private:
     std::string offline_document;
     FileSys::VirtualFile offline_romfs;
 
+    std::string external_url;
+
     Core::System& system;
 };
 
diff --git a/src/yuzu/applets/web_browser.cpp b/src/yuzu/applets/web_browser.cpp
index 7e2dc6ee9..e482ba029 100644
--- a/src/yuzu/applets/web_browser.cpp
+++ b/src/yuzu/applets/web_browser.cpp
@@ -51,59 +51,32 @@ QtNXWebEngineView::QtNXWebEngineView(QWidget* parent, Core::System& system,
                                      InputCommon::InputSubsystem* input_subsystem_)
     : QWebEngineView(parent), input_subsystem{input_subsystem_},
       url_interceptor(std::make_unique<UrlRequestInterceptor>()),
-      input_interpreter(std::make_unique<InputInterpreter>(system)) {
-    QWebEngineScript nx_font_css;
-    QWebEngineScript load_nx_font;
+      input_interpreter(std::make_unique<InputInterpreter>(system)),
+      default_profile{QWebEngineProfile::defaultProfile()},
+      global_settings{QWebEngineSettings::globalSettings()} {
     QWebEngineScript gamepad;
     QWebEngineScript window_nx;
 
-    const QString fonts_dir = QString::fromStdString(Common::FS::SanitizePath(
-        fmt::format("{}/fonts", Common::FS::GetUserPath(Common::FS::UserPath::CacheDir))));
-
-    nx_font_css.setName(QStringLiteral("nx_font_css.js"));
-    load_nx_font.setName(QStringLiteral("load_nx_font.js"));
     gamepad.setName(QStringLiteral("gamepad_script.js"));
     window_nx.setName(QStringLiteral("window_nx_script.js"));
 
-    nx_font_css.setSourceCode(
-        QString::fromStdString(NX_FONT_CSS)
-            .arg(fonts_dir + QStringLiteral("/FontStandard.ttf"))
-            .arg(fonts_dir + QStringLiteral("/FontChineseSimplified.ttf"))
-            .arg(fonts_dir + QStringLiteral("/FontExtendedChineseSimplified.ttf"))
-            .arg(fonts_dir + QStringLiteral("/FontChineseTraditional.ttf"))
-            .arg(fonts_dir + QStringLiteral("/FontKorean.ttf"))
-            .arg(fonts_dir + QStringLiteral("/FontNintendoExtended.ttf"))
-            .arg(fonts_dir + QStringLiteral("/FontNintendoExtended2.ttf")));
-    load_nx_font.setSourceCode(QString::fromStdString(LOAD_NX_FONT));
     gamepad.setSourceCode(QString::fromStdString(GAMEPAD_SCRIPT));
     window_nx.setSourceCode(QString::fromStdString(WINDOW_NX_SCRIPT));
 
-    nx_font_css.setInjectionPoint(QWebEngineScript::DocumentReady);
-    load_nx_font.setInjectionPoint(QWebEngineScript::Deferred);
     gamepad.setInjectionPoint(QWebEngineScript::DocumentCreation);
     window_nx.setInjectionPoint(QWebEngineScript::DocumentCreation);
 
-    nx_font_css.setWorldId(QWebEngineScript::MainWorld);
-    load_nx_font.setWorldId(QWebEngineScript::MainWorld);
     gamepad.setWorldId(QWebEngineScript::MainWorld);
     window_nx.setWorldId(QWebEngineScript::MainWorld);
 
-    nx_font_css.setRunsOnSubFrames(true);
-    load_nx_font.setRunsOnSubFrames(true);
     gamepad.setRunsOnSubFrames(true);
     window_nx.setRunsOnSubFrames(true);
 
-    auto* default_profile = QWebEngineProfile::defaultProfile();
-
-    default_profile->scripts()->insert(nx_font_css);
-    default_profile->scripts()->insert(load_nx_font);
     default_profile->scripts()->insert(gamepad);
     default_profile->scripts()->insert(window_nx);
 
     default_profile->setRequestInterceptor(url_interceptor.get());
 
-    auto* global_settings = QWebEngineSettings::globalSettings();
-
     global_settings->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, true);
     global_settings->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true);
     global_settings->setAttribute(QWebEngineSettings::AllowRunningInsecureContent, true);
@@ -111,13 +84,7 @@ QtNXWebEngineView::QtNXWebEngineView(QWidget* parent, Core::System& system,
     global_settings->setAttribute(QWebEngineSettings::AllowWindowActivationFromJavaScript, true);
     global_settings->setAttribute(QWebEngineSettings::ShowScrollBars, false);
 
-    connect(
-        url_interceptor.get(), &UrlRequestInterceptor::FrameChanged, url_interceptor.get(),
-        [this] {
-            std::this_thread::sleep_for(std::chrono::milliseconds(50));
-            page()->runJavaScript(QString::fromStdString(LOAD_NX_FONT));
-        },
-        Qt::QueuedConnection);
+    global_settings->setFontFamily(QWebEngineSettings::StandardFont, QStringLiteral("Roboto"));
 
     connect(
         page(), &QWebEnginePage::windowCloseRequested, page(),
@@ -137,6 +104,9 @@ QtNXWebEngineView::~QtNXWebEngineView() {
 
 void QtNXWebEngineView::LoadLocalWebPage(std::string_view main_url,
                                          std::string_view additional_args) {
+    is_local = true;
+
+    LoadExtractedFonts();
     SetUserAgent(UserAgent::WebApplet);
     SetFinished(false);
     SetExitReason(Service::AM::Applets::WebExitReason::EndButtonPressed);
@@ -147,6 +117,20 @@ void QtNXWebEngineView::LoadLocalWebPage(std::string_view main_url,
               QString::fromStdString(std::string(additional_args))));
 }
 
+void QtNXWebEngineView::LoadExternalWebPage(std::string_view main_url,
+                                            std::string_view additional_args) {
+    is_local = false;
+
+    SetUserAgent(UserAgent::WebApplet);
+    SetFinished(false);
+    SetExitReason(Service::AM::Applets::WebExitReason::EndButtonPressed);
+    SetLastURL("http://localhost/");
+    StartInputThread();
+
+    load(QUrl(QString::fromStdString(std::string(main_url)) +
+              QString::fromStdString(std::string(additional_args))));
+}
+
 void QtNXWebEngineView::SetUserAgent(UserAgent user_agent) {
     const QString user_agent_str = [user_agent] {
         switch (user_agent) {
@@ -208,11 +192,15 @@ void QtNXWebEngineView::hide() {
 }
 
 void QtNXWebEngineView::keyPressEvent(QKeyEvent* event) {
-    input_subsystem->GetKeyboard()->PressKey(event->key());
+    if (is_local) {
+        input_subsystem->GetKeyboard()->PressKey(event->key());
+    }
 }
 
 void QtNXWebEngineView::keyReleaseEvent(QKeyEvent* event) {
-    input_subsystem->GetKeyboard()->ReleaseKey(event->key());
+    if (is_local) {
+        input_subsystem->GetKeyboard()->ReleaseKey(event->key());
+    }
 }
 
 template <HIDButton... T>
@@ -294,7 +282,10 @@ void QtNXWebEngineView::StartInputThread() {
 }
 
 void QtNXWebEngineView::StopInputThread() {
-    QWidget::releaseKeyboard();
+    if (is_local) {
+        QWidget::releaseKeyboard();
+    }
+
     input_thread_running = false;
     if (input_thread.joinable()) {
         input_thread.join();
@@ -305,7 +296,9 @@ void QtNXWebEngineView::InputThread() {
     // Wait for 1 second before allowing any inputs to be processed.
     std::this_thread::sleep_for(std::chrono::seconds(1));
 
-    QWidget::grabKeyboard();
+    if (is_local) {
+        QWidget::grabKeyboard();
+    }
 
     while (input_thread_running) {
         input_interpreter->PollInput();
@@ -326,11 +319,53 @@ void QtNXWebEngineView::InputThread() {
     }
 }
 
+void QtNXWebEngineView::LoadExtractedFonts() {
+    QWebEngineScript nx_font_css;
+    QWebEngineScript load_nx_font;
+
+    const QString fonts_dir = QString::fromStdString(Common::FS::SanitizePath(
+        fmt::format("{}/fonts", Common::FS::GetUserPath(Common::FS::UserPath::CacheDir))));
+
+    nx_font_css.setName(QStringLiteral("nx_font_css.js"));
+    load_nx_font.setName(QStringLiteral("load_nx_font.js"));
+
+    nx_font_css.setSourceCode(
+        QString::fromStdString(NX_FONT_CSS)
+            .arg(fonts_dir + QStringLiteral("/FontStandard.ttf"))
+            .arg(fonts_dir + QStringLiteral("/FontChineseSimplified.ttf"))
+            .arg(fonts_dir + QStringLiteral("/FontExtendedChineseSimplified.ttf"))
+            .arg(fonts_dir + QStringLiteral("/FontChineseTraditional.ttf"))
+            .arg(fonts_dir + QStringLiteral("/FontKorean.ttf"))
+            .arg(fonts_dir + QStringLiteral("/FontNintendoExtended.ttf"))
+            .arg(fonts_dir + QStringLiteral("/FontNintendoExtended2.ttf")));
+    load_nx_font.setSourceCode(QString::fromStdString(LOAD_NX_FONT));
+
+    nx_font_css.setInjectionPoint(QWebEngineScript::DocumentReady);
+    load_nx_font.setInjectionPoint(QWebEngineScript::Deferred);
+
+    nx_font_css.setWorldId(QWebEngineScript::MainWorld);
+    load_nx_font.setWorldId(QWebEngineScript::MainWorld);
+
+    nx_font_css.setRunsOnSubFrames(true);
+    load_nx_font.setRunsOnSubFrames(true);
+
+    default_profile->scripts()->insert(nx_font_css);
+    default_profile->scripts()->insert(load_nx_font);
+
+    connect(
+        url_interceptor.get(), &UrlRequestInterceptor::FrameChanged, url_interceptor.get(),
+        [this] {
+            std::this_thread::sleep_for(std::chrono::milliseconds(50));
+            page()->runJavaScript(QString::fromStdString(LOAD_NX_FONT));
+        },
+        Qt::QueuedConnection);
+}
+
 #endif
 
 QtWebBrowser::QtWebBrowser(GMainWindow& main_window) {
-    connect(this, &QtWebBrowser::MainWindowOpenLocalWebPage, &main_window,
-            &GMainWindow::WebBrowserOpenLocalWebPage, Qt::QueuedConnection);
+    connect(this, &QtWebBrowser::MainWindowOpenWebPage, &main_window,
+            &GMainWindow::WebBrowserOpenWebPage, Qt::QueuedConnection);
     connect(&main_window, &GMainWindow::WebBrowserExtractOfflineRomFS, this,
             &QtWebBrowser::MainWindowExtractOfflineRomFS, Qt::QueuedConnection);
     connect(&main_window, &GMainWindow::WebBrowserClosed, this,
@@ -340,17 +375,32 @@ QtWebBrowser::QtWebBrowser(GMainWindow& main_window) {
 QtWebBrowser::~QtWebBrowser() = default;
 
 void QtWebBrowser::OpenLocalWebPage(
-    std::string_view local_url, std::function<void()> extract_romfs_callback,
-    std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback) const {
-    this->extract_romfs_callback = std::move(extract_romfs_callback);
-    this->callback = std::move(callback);
+    std::string_view local_url, std::function<void()> extract_romfs_callback_,
+    std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback_) const {
+    extract_romfs_callback = std::move(extract_romfs_callback_);
+    callback = std::move(callback_);
 
     const auto index = local_url.find('?');
 
     if (index == std::string::npos) {
-        emit MainWindowOpenLocalWebPage(local_url, "");
+        emit MainWindowOpenWebPage(local_url, "", true);
     } else {
-        emit MainWindowOpenLocalWebPage(local_url.substr(0, index), local_url.substr(index));
+        emit MainWindowOpenWebPage(local_url.substr(0, index), local_url.substr(index), true);
+    }
+}
+
+void QtWebBrowser::OpenExternalWebPage(
+    std::string_view external_url,
+    std::function<void(Service::AM::Applets::WebExitReason, std::string)> callback_) const {
+    callback = std::move(callback_);
+
+    const auto index = external_url.find('?');
+
+    if (index == std::string::npos) {
+        emit MainWindowOpenWebPage(external_url, "", false);
+    } else {
+        emit MainWindowOpenWebPage(external_url.substr(0, index), external_url.substr(index),
+                                   false);
     }
 }
 
diff --git a/src/yuzu/applets/web_browser.h b/src/yuzu/applets/web_browser.h
index cfddaa6f8..47f960d69 100644
--- a/src/yuzu/applets/web_browser.h
+++ b/src/yuzu/applets/web_browser.h
@@ -18,8 +18,8 @@
 
 enum class HIDButton : u8;
 
-class InputInterpreter;
 class GMainWindow;
+class InputInterpreter;
 class UrlRequestInterceptor;
 
 namespace Core {
@@ -41,6 +41,9 @@ enum class UserAgent {
     WifiWebAuthApplet,
 };
 
+class QWebEngineProfile;
+class QWebEngineSettings;
+
 class QtNXWebEngineView : public QWebEngineView {
     Q_OBJECT
 
@@ -57,6 +60,14 @@ public:
      */
     void LoadLocalWebPage(std::string_view main_url, std::string_view additional_args);
 
+    /**
+     * Loads an external website. Cannot be used to load local urls.
+     *
+     * @param main_url The url to the website.
+     * @param additional_args Additional arguments appended to the main url.
+     */
+    void LoadExternalWebPage(std::string_view main_url, std::string_view additional_args);
+
     /**
      * Sets the background color of the web page.
      *
@@ -147,6 +158,9 @@ private:
     /// The thread where input is being polled and processed.
     void InputThread();
 
+    /// Loads the extracted fonts using JavaScript.
+    void LoadExtractedFonts();
+
     InputCommon::InputSubsystem* input_subsystem;
 
     std::unique_ptr<UrlRequestInterceptor> url_interceptor;
@@ -163,6 +177,11 @@ private:
         Service::AM::Applets::WebExitReason::EndButtonPressed};
 
     std::string last_url{"http://localhost/"};
+
+    bool is_local{};
+
+    QWebEngineProfile* default_profile;
+    QWebEngineSettings* global_settings;
 };
 
 #endif
@@ -174,13 +193,17 @@ public:
     explicit QtWebBrowser(GMainWindow& parent);
     ~QtWebBrowser() override;
 
-    void OpenLocalWebPage(std::string_view local_url, std::function<void()> extract_romfs_callback,
+    void OpenLocalWebPage(std::string_view local_url, std::function<void()> extract_romfs_callback_,
                           std::function<void(Service::AM::Applets::WebExitReason, std::string)>
-                              callback) const override;
+                              callback_) const override;
+
+    void OpenExternalWebPage(std::string_view external_url,
+                             std::function<void(Service::AM::Applets::WebExitReason, std::string)>
+                                 callback_) const override;
 
 signals:
-    void MainWindowOpenLocalWebPage(std::string_view main_url,
-                                    std::string_view additional_args) const;
+    void MainWindowOpenWebPage(std::string_view main_url, std::string_view additional_args,
+                               bool is_local) const;
 
 private:
     void MainWindowExtractOfflineRomFS();
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index f835ee9cb..620e80cdc 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -366,13 +366,13 @@ void GMainWindow::SoftwareKeyboardInvokeCheckDialog(std::u16string error_message
     emit SoftwareKeyboardFinishedCheckDialog();
 }
 
-void GMainWindow::WebBrowserOpenLocalWebPage(std::string_view main_url,
-                                             std::string_view additional_args) {
+void GMainWindow::WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args,
+                                        bool is_local) {
 #ifdef YUZU_USE_QT_WEB_ENGINE
 
     if (disable_web_applet) {
         emit WebBrowserClosed(Service::AM::Applets::WebExitReason::WindowClosed,
-                              "http://localhost");
+                              "http://localhost/");
         return;
     }
 
@@ -388,7 +388,7 @@ void GMainWindow::WebBrowserOpenLocalWebPage(std::string_view main_url,
         loading_progress.setRange(0, 3);
         loading_progress.setValue(0);
 
-        if (!Common::FS::Exists(std::string(main_url))) {
+        if (is_local && !Common::FS::Exists(std::string(main_url))) {
             loading_progress.show();
 
             auto future = QtConcurrent::run([this] { emit WebBrowserExtractOfflineRomFS(); });
@@ -400,7 +400,11 @@ void GMainWindow::WebBrowserOpenLocalWebPage(std::string_view main_url,
 
         loading_progress.setValue(1);
 
-        web_browser_view.LoadLocalWebPage(main_url, additional_args);
+        if (is_local) {
+            web_browser_view.LoadLocalWebPage(main_url, additional_args);
+        } else {
+            web_browser_view.LoadExternalWebPage(main_url, additional_args);
+        }
 
         if (render_window->IsLoadingComplete()) {
             render_window->hide();
@@ -493,7 +497,7 @@ void GMainWindow::WebBrowserOpenLocalWebPage(std::string_view main_url,
 #else
 
     // Utilize the same fallback as the default web browser applet.
-    emit WebBrowserClosed(Service::AM::Applets::WebExitReason::WindowClosed, "http://localhost");
+    emit WebBrowserClosed(Service::AM::Applets::WebExitReason::WindowClosed, "http://localhost/");
 
 #endif
 }
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index b140995bf..22f82b20e 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -142,7 +142,8 @@ public slots:
     void ProfileSelectorSelectProfile();
     void SoftwareKeyboardGetText(const Core::Frontend::SoftwareKeyboardParameters& parameters);
     void SoftwareKeyboardInvokeCheckDialog(std::u16string error_message);
-    void WebBrowserOpenLocalWebPage(std::string_view main_url, std::string_view additional_args);
+    void WebBrowserOpenWebPage(std::string_view main_url, std::string_view additional_args,
+                               bool is_local);
     void OnAppFocusStateChanged(Qt::ApplicationState state);
 
 private: