diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index f2f6e31131..b48db705a7 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -46,6 +46,7 @@ QT_MOC_CPP = \
   qml/models/moc_peerlistsortproxy.cpp \
   qml/models/moc_transaction.cpp \
   qml/models/moc_sendrecipient.cpp \
+  qml/models/moc_snapshotqml.cpp \
   qml/models/moc_walletlistmodel.cpp \
   qml/models/moc_walletqmlmodel.cpp \
   qml/models/moc_walletqmlmodel.cpp \
@@ -136,6 +137,7 @@ BITCOIN_QT_H = \
   qml/models/peerlistsortproxy.h \
   qml/models/transaction.h \
   qml/models/sendrecipient.h \
+  qml/models/snapshotqml.h \
   qml/models/walletlistmodel.h \
   qml/models/walletqmlmodel.h \
   qml/models/walletqmlmodeltransaction.h \
@@ -335,6 +337,7 @@ BITCOIN_QML_BASE_CPP = \
   qml/models/peerlistsortproxy.cpp \
   qml/models/transaction.cpp \
   qml/models/sendrecipient.cpp \
+  qml/models/snapshotqml.cpp \
   qml/models/walletlistmodel.cpp \
   qml/models/walletqmlmodel.cpp \
   qml/models/walletqmlmodeltransaction.cpp \
@@ -360,12 +363,15 @@ QML_RES_ICONS = \
   qml/res/icons/check.png \
   qml/res/icons/copy.png \
   qml/res/icons/coinbase.png \
+  qml/res/icons/circle-file.png \
+  qml/res/icons/circle-green-check.png \
   qml/res/icons/cross.png \
   qml/res/icons/error.png \
   qml/res/icons/export.png \
   qml/res/icons/flip-vertical.png \
   qml/res/icons/gear.png \
   qml/res/icons/gear-outline.png \
+  qml/res/icons/green-check.png \
   qml/res/icons/hidden.png \
   qml/res/icons/info.png \
   qml/res/icons/minus.png \
@@ -400,6 +406,7 @@ QML_RES_QML = \
   qml/components/NetworkIndicator.qml \
   qml/components/ProxySettings.qml \
   qml/components/Separator.qml \
+  qml/components/SnapshotSettings.qml \
   qml/components/StorageLocations.qml \
   qml/components/StorageOptions.qml \
   qml/components/StorageSettings.qml \
@@ -457,6 +464,7 @@ QML_RES_QML = \
   qml/pages/settings/SettingsDeveloper.qml \
   qml/pages/settings/SettingsDisplay.qml \
   qml/pages/settings/SettingsProxy.qml \
+  qml/pages/settings/SettingsSnapshot.qml \
   qml/pages/settings/SettingsStorage.qml \
   qml/pages/settings/SettingsTheme.qml \
   qml/pages/wallet/Activity.qml \
diff --git a/src/interfaces/node.h b/src/interfaces/node.h
index 1aab36927b..b50643db22 100644
--- a/src/interfaces/node.h
+++ b/src/interfaces/node.h
@@ -11,6 +11,7 @@
 #include <net_types.h>                 // For banmap_t
 #include <netaddress.h>                // For Network
 #include <netbase.h>                   // For ConnectionDirection
+#include <node/utxo_snapshot.h>         // For SnapshotMetadata
 #include <support/allocators/secure.h> // For SecureString
 #include <util/translation.h>
 
@@ -208,6 +209,9 @@ class Node
     //! List rpc commands.
     virtual std::vector<std::string> listRpcCommands() = 0;
 
+    //! Load UTXO Snapshot.
+    virtual bool loadSnapshot(AutoFile& afile, const node::SnapshotMetadata& metadata, bool in_memory) = 0;
+
     //! Set RPC timer interface if unset.
     virtual void rpcSetTimerInterfaceIfUnset(RPCTimerInterface* iface) = 0;
 
@@ -243,6 +247,10 @@ class Node
     using ShowProgressFn = std::function<void(const std::string& title, int progress, bool resume_possible)>;
     virtual std::unique_ptr<Handler> handleShowProgress(ShowProgressFn fn) = 0;
 
+    //! Register handler for snapshot load progress.
+    using SnapshotLoadProgressFn = std::function<void(double progress)>;
+    virtual std::unique_ptr<Handler> handleSnapshotLoadProgress(SnapshotLoadProgressFn fn) = 0;
+
     //! Register handler for wallet loader constructed messages.
     using InitWalletFn = std::function<void()>;
     virtual std::unique_ptr<Handler> handleInitWallet(InitWalletFn fn) = 0;
diff --git a/src/kernel/chainparams.cpp b/src/kernel/chainparams.cpp
index 733a3339b3..635dc40f9f 100644
--- a/src/kernel/chainparams.cpp
+++ b/src/kernel/chainparams.cpp
@@ -371,6 +371,13 @@ class SigNetParams : public CChainParams {
 
         vFixedSeeds.clear();
 
+        m_assumeutxo_data = MapAssumeutxo{
+            {
+                160000,
+                {AssumeutxoHash{uint256S("0x5225141cb62dee63ab3be95f9b03d60801f264010b1816d4bd00618b2736e7be")}, 1278002},
+            },
+        };
+
         base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,111);
         base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,196);
         base58Prefixes[SECRET_KEY] =     std::vector<unsigned char>(1,239);
diff --git a/src/kernel/notifications_interface.h b/src/kernel/notifications_interface.h
index c5e77b0df9..b8002dedd2 100644
--- a/src/kernel/notifications_interface.h
+++ b/src/kernel/notifications_interface.h
@@ -40,6 +40,7 @@ class Notifications
     [[nodiscard]] virtual InterruptResult blockTip(SynchronizationState state, CBlockIndex& index) { return {}; }
     virtual void headerTip(SynchronizationState state, int64_t height, int64_t timestamp, bool presync) {}
     virtual void progress(const bilingual_str& title, int progress_percent, bool resume_possible) {}
+    virtual void snapshotLoadProgress(double progress) {}
     virtual void warning(const bilingual_str& warning) {}
 
     //! The flush error notification is sent to notify the user that an error
diff --git a/src/node/interface_ui.cpp b/src/node/interface_ui.cpp
index a1664f1bad..a57a559146 100644
--- a/src/node/interface_ui.cpp
+++ b/src/node/interface_ui.cpp
@@ -21,6 +21,7 @@ struct UISignals {
     boost::signals2::signal<CClientUIInterface::NotifyNetworkActiveChangedSig> NotifyNetworkActiveChanged;
     boost::signals2::signal<CClientUIInterface::NotifyAlertChangedSig> NotifyAlertChanged;
     boost::signals2::signal<CClientUIInterface::ShowProgressSig> ShowProgress;
+    boost::signals2::signal<CClientUIInterface::SnapshotLoadProgressSig> SnapshotLoadProgress;
     boost::signals2::signal<CClientUIInterface::NotifyBlockTipSig> NotifyBlockTip;
     boost::signals2::signal<CClientUIInterface::NotifyHeaderTipSig> NotifyHeaderTip;
     boost::signals2::signal<CClientUIInterface::BannedListChangedSig> BannedListChanged;
@@ -44,6 +45,7 @@ ADD_SIGNALS_IMPL_WRAPPER(ShowProgress);
 ADD_SIGNALS_IMPL_WRAPPER(NotifyBlockTip);
 ADD_SIGNALS_IMPL_WRAPPER(NotifyHeaderTip);
 ADD_SIGNALS_IMPL_WRAPPER(BannedListChanged);
+ADD_SIGNALS_IMPL_WRAPPER(SnapshotLoadProgress);
 
 bool CClientUIInterface::ThreadSafeMessageBox(const bilingual_str& message, const std::string& caption, unsigned int style) { return g_ui_signals.ThreadSafeMessageBox(message, caption, style).value_or(false);}
 bool CClientUIInterface::ThreadSafeQuestion(const bilingual_str& message, const std::string& non_interactive_message, const std::string& caption, unsigned int style) { return g_ui_signals.ThreadSafeQuestion(message, non_interactive_message, caption, style).value_or(false);}
@@ -53,6 +55,7 @@ void CClientUIInterface::NotifyNumConnectionsChanged(PeersNumByType newNumConnec
 void CClientUIInterface::NotifyNetworkActiveChanged(bool networkActive) { return g_ui_signals.NotifyNetworkActiveChanged(networkActive); }
 void CClientUIInterface::NotifyAlertChanged() { return g_ui_signals.NotifyAlertChanged(); }
 void CClientUIInterface::ShowProgress(const std::string& title, int nProgress, bool resume_possible) { return g_ui_signals.ShowProgress(title, nProgress, resume_possible); }
+void CClientUIInterface::SnapshotLoadProgress(double progress) { return g_ui_signals.SnapshotLoadProgress(progress); }
 void CClientUIInterface::NotifyBlockTip(SynchronizationState s, const CBlockIndex* i) { return g_ui_signals.NotifyBlockTip(s, i); }
 void CClientUIInterface::NotifyHeaderTip(SynchronizationState s, int64_t height, int64_t timestamp, bool presync) { return g_ui_signals.NotifyHeaderTip(s, height, timestamp, presync); }
 void CClientUIInterface::BannedListChanged() { return g_ui_signals.BannedListChanged(); }
diff --git a/src/node/interface_ui.h b/src/node/interface_ui.h
index cb5a9cbafd..14d3761898 100644
--- a/src/node/interface_ui.h
+++ b/src/node/interface_ui.h
@@ -109,6 +109,9 @@ class CClientUIInterface
      */
     ADD_SIGNALS_DECL_WRAPPER(ShowProgress, void, const std::string& title, int nProgress, bool resume_possible);
 
+    /** Snapshot load progress. */
+    ADD_SIGNALS_DECL_WRAPPER(SnapshotLoadProgress, void, double progress);
+
     /** New block has been accepted */
     ADD_SIGNALS_DECL_WRAPPER(NotifyBlockTip, void, SynchronizationState, const CBlockIndex*);
 
diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp
index 3dd867cb8d..4d88822a8a 100644
--- a/src/node/interfaces.cpp
+++ b/src/node/interfaces.cpp
@@ -29,6 +29,7 @@
 #include <node/context.h>
 #include <node/interface_ui.h>
 #include <node/transaction.h>
+#include <node/utxo_snapshot.h>
 #include <policy/feerate.h>
 #include <policy/fees.h>
 #include <policy/policy.h>
@@ -378,6 +379,10 @@ class NodeImpl : public Node
     {
         return MakeSignalHandler(::uiInterface.ShowProgress_connect(fn));
     }
+    std::unique_ptr<Handler> handleSnapshotLoadProgress(SnapshotLoadProgressFn fn) override
+    {
+        return MakeSignalHandler(::uiInterface.SnapshotLoadProgress_connect(fn));
+    }
     std::unique_ptr<Handler> handleInitWallet(InitWalletFn fn) override
     {
         return MakeSignalHandler(::uiInterface.InitWallet_connect(fn));
@@ -417,6 +422,10 @@ class NodeImpl : public Node
     {
         m_context = context;
     }
+    bool loadSnapshot(AutoFile& afile, const node::SnapshotMetadata& metadata, bool in_memory) override
+    {
+        return chainman().ActivateSnapshot(afile, metadata, in_memory);
+    }
     ArgsManager& args() { return *Assert(Assert(m_context)->args); }
     ChainstateManager& chainman() { return *Assert(m_context->chainman); }
     NodeContext* m_context{nullptr};
@@ -532,7 +541,7 @@ class RpcHandlerImpl : public Handler
 class ChainImpl : public Chain
 {
 public:
-    explicit ChainImpl(NodeContext& node) : m_node(node) {}
+    explicit ChainImpl(node::NodeContext& node) : m_node(node) {}
     std::optional<int> getHeight() override
     {
         const int height{WITH_LOCK(::cs_main, return chainman().ActiveChain().Height())};
diff --git a/src/node/kernel_notifications.cpp b/src/node/kernel_notifications.cpp
index 7224127c72..e41308dd50 100644
--- a/src/node/kernel_notifications.cpp
+++ b/src/node/kernel_notifications.cpp
@@ -78,6 +78,11 @@ void KernelNotifications::progress(const bilingual_str& title, int progress_perc
     uiInterface.ShowProgress(title.translated, progress_percent, resume_possible);
 }
 
+void KernelNotifications::snapshotLoadProgress(double progress)
+{
+    uiInterface.SnapshotLoadProgress(progress);
+}
+
 void KernelNotifications::warning(const bilingual_str& warning)
 {
     DoWarning(warning);
diff --git a/src/node/kernel_notifications.h b/src/node/kernel_notifications.h
index b2dfc03398..4e9b9f77db 100644
--- a/src/node/kernel_notifications.h
+++ b/src/node/kernel_notifications.h
@@ -31,6 +31,8 @@ class KernelNotifications : public kernel::Notifications
 
     void progress(const bilingual_str& title, int progress_percent, bool resume_possible) override;
 
+    void snapshotLoadProgress(double progress) override;
+
     void warning(const bilingual_str& warning) override;
 
     void flushError(const std::string& debug_message) override;
diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc
index 69a07de568..877469e933 100644
--- a/src/qml/bitcoin_qml.qrc
+++ b/src/qml/bitcoin_qml.qrc
@@ -15,6 +15,7 @@
         <file>components/ProxySettings.qml</file>
         <file>components/StorageLocations.qml</file>
         <file>components/Separator.qml</file>
+        <file>components/SnapshotSettings.qml</file>
         <file>components/StorageOptions.qml</file>
         <file>components/StorageSettings.qml</file>
         <file>components/ThemeSettings.qml</file>
@@ -26,6 +27,7 @@
         <file>controls/CoreTextField.qml</file>
         <file>controls/ExternalLink.qml</file>
         <file>controls/FocusBorder.qml</file>
+        <file>controls/GreenCheckIcon.qml</file>
         <file>controls/Header.qml</file>
         <file>controls/Icon.qml</file>
         <file>controls/InformationPage.qml</file>
@@ -70,6 +72,7 @@
         <file>pages/settings/SettingsDeveloper.qml</file>
         <file>pages/settings/SettingsDisplay.qml</file>
         <file>pages/settings/SettingsProxy.qml</file>
+        <file>pages/settings/SettingsSnapshot.qml</file>
         <file>pages/settings/SettingsStorage.qml</file>
         <file>pages/settings/SettingsTheme.qml</file>
         <file>pages/wallet/Activity.qml</file>
@@ -103,12 +106,15 @@
         <file alias="check">res/icons/check.png</file>
         <file alias="copy">res/icons/copy.png</file>
         <file alias="coinbase">res/icons/coinbase.png</file>
+        <file alias="circle-file">res/icons/circle-file.png</file>
+        <file alias="circle-green-check">res/icons/circle-green-check.png</file>
         <file alias="cross">res/icons/cross.png</file>
         <file alias="error">res/icons/error.png</file>
         <file alias="export">res/icons/export.png</file>
         <file alias="flip-vertical">res/icons/flip-vertical.png</file>
         <file alias="gear">res/icons/gear.png</file>
         <file alias="gear-outline">res/icons/gear-outline.png</file>
+        <file alias="green-check">res/icons/green-check.png</file>
         <file alias="hidden">res/icons/hidden.png</file>
         <file alias="info">res/icons/info.png</file>
         <file alias="minus">res/icons/minus.png</file>
diff --git a/src/qml/components/ConnectionSettings.qml b/src/qml/components/ConnectionSettings.qml
index 35e78b7a6e..d5f772eac8 100644
--- a/src/qml/components/ConnectionSettings.qml
+++ b/src/qml/components/ConnectionSettings.qml
@@ -10,7 +10,37 @@ import "../controls"
 ColumnLayout {
     id: root
     signal next
+    signal gotoSnapshot
+    property bool onboarding: false
+    property bool snapshotImportCompleted: onboarding ? false : chainModel.isSnapshotActive
     spacing: 4
+    Setting {
+        id: gotoSnapshot
+        visible: !root.onboarding && !snapshotImportCompleted
+        Layout.fillWidth: true
+        header: qsTr("Load snapshot")
+        description: qsTr("Instant use with background sync")
+        actionItem: Item {
+            width: 26
+            height: 26
+            CaretRightIcon {
+                anchors.centerIn: parent
+                visible: !snapshotImportCompleted
+                color: gotoSnapshot.stateColor
+            }
+            GreenCheckIcon {
+                anchors.centerIn: parent
+                visible: snapshotImportCompleted
+                color: Theme.color.transparent
+                size: 30
+            }
+        }
+        onClicked: root.gotoSnapshot()
+    }
+    Separator {
+        visible: !root.onboarding && !snapshotImportCompleted
+        Layout.fillWidth: true
+    }
     Setting {
         Layout.fillWidth: true
         header: qsTr("Enable listening")
diff --git a/src/qml/components/SnapshotSettings.qml b/src/qml/components/SnapshotSettings.qml
new file mode 100644
index 0000000000..1c73f8af18
--- /dev/null
+++ b/src/qml/components/SnapshotSettings.qml
@@ -0,0 +1,229 @@
+// Copyright (c) 2023-present The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Layouts 1.15
+import QtQuick.Dialogs 1.3
+
+import "../controls"
+
+ColumnLayout {
+    id: columnLayout
+    signal back
+    property bool snapshotLoading: nodeModel.snapshotLoading
+    property bool snapshotLoaded: nodeModel.isSnapshotLoaded
+    property bool snapshotImportCompleted: onboarding ? false : chainModel.isSnapshotActive
+    property bool onboarding: false
+    property bool snapshotVerified: onboarding ? false : chainModel.isSnapshotActive
+    property string snapshotFileName: ""
+    property var snapshotInfo: (snapshotVerified || snapshotLoaded) ? chainModel.getSnapshotInfo() : ({})
+    property string selectedFile: ""
+    property bool headersSynced: nodeModel.headersSynced
+
+    width: Math.min(parent.width, 450)
+    anchors.horizontalCenter: parent.horizontalCenter
+
+    StackLayout {
+        id: settingsStack
+        currentIndex: onboarding ? 0 : snapshotLoaded ? 2 : snapshotVerified ? 2 : snapshotLoading ? 1 : 0
+
+        ColumnLayout {
+            Layout.alignment: Qt.AlignHCenter
+            Layout.preferredWidth: Math.min(parent.width, 450)
+
+            Image {
+                Layout.alignment: Qt.AlignCenter
+                source: "image://images/circle-file"
+
+                sourceSize.width: 200
+                sourceSize.height: 200
+            }
+
+            Header {
+                Layout.fillWidth: true
+                Layout.topMargin: 20
+                headerBold: true
+                header: qsTr("Load snapshot")
+                descriptionBold: false
+                descriptionColor: Theme.color.neutral6
+                descriptionSize: 17
+                descriptionLineHeight: 1.1
+                description: qsTr("You can start using the application more quickly by loading a recent transaction snapshot." +
+                " It will be automatically verified in the background.")
+            }
+
+            CoreText {
+                Layout.fillWidth: true
+                Layout.topMargin: 20
+                color: Theme.color.neutral6
+                font.pixelSize: 17
+                visible: !headersSynced
+                text: !headersSynced
+                    ? qsTr("Please wait for headers to sync before loading a snapshot.")
+                    : qsTr("")
+                wrap: true
+                wrapMode: Text.WordWrap
+            }
+
+            ContinueButton {
+                Layout.preferredWidth: Math.min(300, columnLayout.width - 2 * Layout.leftMargin)
+                Layout.topMargin: 40
+                Layout.leftMargin: 20
+                Layout.rightMargin: Layout.leftMargin
+                Layout.bottomMargin: 20
+                Layout.alignment: Qt.AlignCenter
+                text: qsTr("Choose snapshot file")
+                enabled: headersSynced
+                onClicked: fileDialog.open()
+            }
+
+            FileDialog {
+                id: fileDialog
+                folder: shortcuts.home
+                selectMultiple: false
+                selectExisting: true
+                nameFilters: ["Snapshot files (*.dat)", "All files (*)"]
+                onAccepted: {
+                    selectedFile = fileUrl.toString()
+                    snapshotFileName = selectedFile
+                    nodeModel.snapshotLoadThread(snapshotFileName)
+                }
+            }
+            // TODO: Handle file error signal
+        }
+
+        ColumnLayout {
+            Layout.alignment: Qt.AlignHCenter
+            Layout.preferredWidth: Math.min(parent.width, 450)
+
+            Image {
+                Layout.alignment: Qt.AlignCenter
+                source: "image://images/circle-file"
+
+                sourceSize.width: 200
+                sourceSize.height: 200
+            }
+
+            Header {
+                Layout.fillWidth: true
+                Layout.topMargin: 20
+                Layout.leftMargin: 20
+                Layout.rightMargin: 20
+                header: qsTr("Loading Snapshot")
+                description: qsTr("This might take a while...")
+            }
+
+            ProgressIndicator {
+                id: progressIndicator
+                Layout.topMargin: 20
+                width: 200
+                height: 20
+                progress: nodeModel.snapshotProgress
+                Layout.alignment: Qt.AlignCenter
+                progressColor: Theme.color.blue
+            }
+        }
+
+        ColumnLayout {
+            id: loadedSnapshotColumn
+            Layout.alignment: Qt.AlignHCenter
+            Layout.preferredWidth: Math.min(parent.width, 450)
+
+            Image {
+                Layout.alignment: Qt.AlignCenter
+                source: "image://images/circle-green-check"
+
+                sourceSize.width: 60
+                sourceSize.height: 60
+            }
+
+            Header {
+                Layout.fillWidth: true
+                Layout.topMargin: 20
+                headerBold: true
+                header: qsTr("Snapshot Loaded")
+                descriptionBold: false
+                descriptionColor: Theme.color.neutral6
+                descriptionSize: 17
+                descriptionLineHeight: 1.1
+                description: snapshotInfo && snapshotInfo["date"] ?
+                    qsTr("It contains unspent transactions up to %1. Next, transactions will be verified and newer transactions downloaded.").arg(snapshotInfo["date"]) :
+                    qsTr("It contains transactions up to DEBUG. Newer transactions still need to be downloaded." +
+                    " The data will be verified in the background.")
+            }
+
+            ContinueButton {
+                Layout.preferredWidth: Math.min(300, columnLayout.width - 2 * Layout.leftMargin)
+                Layout.topMargin: 40
+                Layout.alignment: Qt.AlignCenter
+                text: qsTr("Done")
+                onClicked: {
+                    chainModel.isSnapshotActiveChanged()
+                    back()
+                }
+            }
+
+            Setting {
+                id: viewDetails
+                Layout.alignment: Qt.AlignCenter
+                header: qsTr("View details")
+                actionItem: CaretRightIcon {
+                    id: caretIcon
+                    color: viewDetails.stateColor
+                    rotation: viewDetails.expanded ? 90 : 0
+                    Behavior on rotation { NumberAnimation { duration: 200 } }
+                }
+
+                property bool expanded: false
+
+                onClicked: {
+                    expanded = !expanded
+                }
+            }
+
+            ColumnLayout {
+                id: detailsContent
+                visible: viewDetails.expanded
+                Layout.preferredWidth: Math.min(300, parent.width - 2 * Layout.leftMargin)
+                Layout.alignment: Qt.AlignCenter
+                Layout.leftMargin: 80
+                Layout.rightMargin: 80
+                Layout.topMargin: 10
+                spacing: 10
+                // TODO: make sure the block height number aligns right
+                RowLayout {
+                    CoreText {
+                        text: qsTr("Block Height:")
+                        Layout.alignment: Qt.AlignLeft
+                        font.pixelSize: 14
+                    }
+                    CoreText {
+                        text: snapshotInfo && snapshotInfo["height"] ?
+                            snapshotInfo["height"] : qsTr("DEBUG")
+                        Layout.alignment: Qt.AlignRight
+                        font.pixelSize: 14
+                    }
+                }
+                Separator { Layout.fillWidth: true }
+                ColumnLayout {
+                    Layout.fillWidth: true
+                    spacing: 5
+                    CoreText {
+                        text: qsTr("Hash:")
+                        font.pixelSize: 14
+                    }
+                    CoreText {
+                        text: snapshotInfo && snapshotInfo["hashSerializedFirstHalf"] ?
+                            snapshotInfo["hashSerializedFirstHalf"] + "\n" + snapshotInfo["hashSerializedSecondHalf"] :
+                            qsTr("DEBUG")
+                        Layout.fillWidth: true
+                        font.pixelSize: 14
+                        textFormat: Text.PlainText
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/src/qml/controls/GreenCheckIcon.qml b/src/qml/controls/GreenCheckIcon.qml
new file mode 100644
index 0000000000..02977857b2
--- /dev/null
+++ b/src/qml/controls/GreenCheckIcon.qml
@@ -0,0 +1,11 @@
+// Copyright (c) 2023 - present The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+
+Icon {
+    source: "image://images/green-check"
+    size: 30
+}
diff --git a/src/qml/controls/Header.qml b/src/qml/controls/Header.qml
index f3c4c0c3e3..ece49234d2 100644
--- a/src/qml/controls/Header.qml
+++ b/src/qml/controls/Header.qml
@@ -25,6 +25,7 @@ ColumnLayout {
     property int subtextSize: 15
     property color subtextColor: Theme.color.neutral9
     property bool wrap: true
+    property real descriptionLineHeight: 1
 
     spacing: 0
     Loader {
@@ -60,6 +61,7 @@ ColumnLayout {
             text: root.description
             horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft
             wrapMode: wrap ? Text.WordWrap : Text.NoWrap
+            lineHeight: root.descriptionLineHeight
 
             Behavior on color {
                 ColorAnimation { duration: 150 }
diff --git a/src/qml/controls/ProgressIndicator.qml b/src/qml/controls/ProgressIndicator.qml
index 117a4baebb..9d6d62d329 100644
--- a/src/qml/controls/ProgressIndicator.qml
+++ b/src/qml/controls/ProgressIndicator.qml
@@ -7,6 +7,7 @@ import QtQuick.Controls 2.15
 
 Control {
     property real progress: 0
+    property color progressColor: Theme.color.orange
     Behavior on progress {
         NumberAnimation {
             easing.type: Easing.Bezier
@@ -26,7 +27,7 @@ Control {
                 width: contentItem.width
                 height: contentItem.height
                 radius: contentItem.radius
-                color: Theme.color.orange
+                color: progressColor
             }
         }
     }
diff --git a/src/qml/controls/Theme.qml b/src/qml/controls/Theme.qml
index f57e152cbd..3c7621c2b5 100644
--- a/src/qml/controls/Theme.qml
+++ b/src/qml/controls/Theme.qml
@@ -27,6 +27,7 @@ Control {
         required property color blue
         required property color amber
         required property color purple
+        required property color transparent
         required property color neutral0
         required property color neutral1
         required property color neutral2
@@ -59,6 +60,7 @@ Control {
         blue: "#3CA3DE"
         amber: "#C9B500"
         purple: "#C075DC"
+        transparent: "#00000000"
         neutral0: "#000000"
         neutral1: "#1A1A1A"
         neutral2: "#2D2D2D"
@@ -91,6 +93,7 @@ Control {
         blue: "#2D9CDB"
         amber: "#C9B500"
         purple: "#BB6BD9"
+        transparent: "#00000000"
         neutral0: "#FFFFFF"
         neutral1: "#F8F8F8"
         neutral2: "#F4F4F4"
diff --git a/src/qml/imageprovider.cpp b/src/qml/imageprovider.cpp
index aeed8a5b97..729cd82617 100644
--- a/src/qml/imageprovider.cpp
+++ b/src/qml/imageprovider.cpp
@@ -87,6 +87,16 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize
         return QIcon(":/icons/copy").pixmap(requested_size);
     }
 
+    if (id == "circle-file") {
+        *size = requested_size;
+        return QIcon(":/icons/circle-file").pixmap(requested_size);
+    }
+
+    if (id == "circle-green-check") {
+        *size = requested_size;
+        return QIcon(":/icons/circle-green-check").pixmap(requested_size);
+    }
+
     if (id == "cross") {
         *size = requested_size;
         return QIcon(":/icons/cross").pixmap(requested_size);
@@ -117,6 +127,11 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize
         return QIcon(":/icons/gear-outline").pixmap(requested_size);
     }
 
+    if (id == "green-check") {
+        *size = requested_size;
+        return QIcon(":/icons/green-check").pixmap(requested_size);
+    }
+
     if (id == "info") {
         *size = requested_size;
         return QIcon(":/icons/info").pixmap(requested_size);
diff --git a/src/qml/models/chainmodel.cpp b/src/qml/models/chainmodel.cpp
index aeffe99599..978046ebff 100644
--- a/src/qml/models/chainmodel.cpp
+++ b/src/qml/models/chainmodel.cpp
@@ -9,9 +9,13 @@
 #include <QThread>
 #include <QTime>
 #include <interfaces/chain.h>
+#include <node/utxo_snapshot.h>
+#include <kernel/chainparams.h>
+#include <validation.h>
 
 ChainModel::ChainModel(interfaces::Chain& chain)
     : m_chain{chain}
+    //   m_params{Params()}
 {
     QTimer* timer = new QTimer();
     connect(timer, &QTimer::timeout, this, &ChainModel::setCurrentTimeRatio);
@@ -101,3 +105,29 @@ void ChainModel::setCurrentTimeRatio()
 
     Q_EMIT timeRatioListChanged();
 }
+
+// TODO: Change this once a better solution has been found.
+// Using hardcoded snapshot info to display in SnapshotSettings.qml
+QVariantMap ChainModel::getSnapshotInfo() {
+    QVariantMap snapshot_info;
+
+   const MapAssumeutxo& valid_assumeutxos_map = Params().Assumeutxo();
+    if (!valid_assumeutxos_map.empty()) {
+        const int height = valid_assumeutxos_map.rbegin()->first;
+        const auto& hash_serialized = valid_assumeutxos_map.rbegin()->second.hash_serialized;
+        int64_t date = m_chain.getBlockTime(height);
+
+        QString fullHash = QString::fromStdString(hash_serialized.ToString());
+
+        int midPoint = fullHash.length() / 2;
+        QString firstHalf = fullHash.left(midPoint);
+        QString secondHalf = fullHash.mid(midPoint);
+
+        snapshot_info["height"] = height;
+        snapshot_info["hashSerializedFirstHalf"] = firstHalf;
+        snapshot_info["hashSerializedSecondHalf"] = secondHalf;
+        snapshot_info["date"] = QDateTime::fromSecsSinceEpoch(date).toString("MMMM d yyyy");
+    }
+
+    return snapshot_info;
+}
diff --git a/src/qml/models/chainmodel.h b/src/qml/models/chainmodel.h
index 9318510eda..6a5124be7f 100644
--- a/src/qml/models/chainmodel.h
+++ b/src/qml/models/chainmodel.h
@@ -27,6 +27,7 @@ class ChainModel : public QObject
     Q_PROPERTY(quint64 assumedBlockchainSize READ assumedBlockchainSize CONSTANT)
     Q_PROPERTY(quint64 assumedChainstateSize READ assumedChainstateSize CONSTANT)
     Q_PROPERTY(QVariantList timeRatioList READ timeRatioList NOTIFY timeRatioListChanged)
+    Q_PROPERTY(bool isSnapshotActive READ isSnapshotActive NOTIFY isSnapshotActiveChanged)
 
 public:
     explicit ChainModel(interfaces::Chain& chain);
@@ -36,11 +37,13 @@ class ChainModel : public QObject
     quint64 assumedBlockchainSize() const { return m_assumed_blockchain_size; };
     quint64 assumedChainstateSize() const { return m_assumed_chainstate_size; };
     QVariantList timeRatioList() const { return m_time_ratio_list; };
-
+    bool isSnapshotActive() const { return m_chain.hasAssumedValidChain(); };
     int timestampAtMeridian();
 
     void setCurrentTimeRatio();
 
+    Q_INVOKABLE QVariantMap getSnapshotInfo();
+
 public Q_SLOTS:
     void setTimeRatioList(int new_time);
     void setTimeRatioListInitial();
@@ -48,6 +51,7 @@ public Q_SLOTS:
 Q_SIGNALS:
     void timeRatioListChanged();
     void currentNetworkNameChanged();
+    void isSnapshotActiveChanged();
 
 private:
     QString m_current_network_name;
diff --git a/src/qml/models/nodemodel.cpp b/src/qml/models/nodemodel.cpp
index 8ccc532016..2078650032 100644
--- a/src/qml/models/nodemodel.cpp
+++ b/src/qml/models/nodemodel.cpp
@@ -3,6 +3,7 @@
 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
 
 #include <qml/models/nodemodel.h>
+#include <qml/models/snapshotqml.h>
 
 #include <interfaces/node.h>
 #include <net.h>
@@ -14,14 +15,19 @@
 
 #include <QDateTime>
 #include <QMetaObject>
+#include <QObject>
 #include <QTimerEvent>
 #include <QString>
+#include <QUrl>
+#include <QThread>
+#include <QDebug>
 
 NodeModel::NodeModel(interfaces::Node& node)
     : m_node{node}
 {
     ConnectToBlockTipSignal();
     ConnectToNumConnectionsChangedSignal();
+    ConnectToSnapshotLoadProgressSignal();
 }
 
 void NodeModel::setBlockTipHeight(int new_height)
@@ -80,6 +86,10 @@ void NodeModel::setVerificationProgress(double new_progress)
     if (new_progress != m_verification_progress) {
         setRemainingSyncTime(new_progress);
 
+        if (new_progress >= 0.00001) {
+            setHeadersSynced(true);
+        }
+
         m_verification_progress = new_progress;
         Q_EMIT verificationProgressChanged();
     }
@@ -176,3 +186,51 @@ QString NodeModel::defaultProxyAddress()
 {
     return QString::fromStdString(m_node.defaultProxyAddress());
 }
+
+void NodeModel::ConnectToSnapshotLoadProgressSignal()
+{
+    assert(!m_handler_snapshot_load_progress);
+
+    m_handler_snapshot_load_progress = m_node.handleSnapshotLoadProgress(
+        [this](double progress) {
+            setSnapshotProgress(progress);
+        });
+}
+
+void NodeModel::snapshotLoadThread(QString path_file) {
+    m_snapshot_loading = true;
+    Q_EMIT snapshotLoadingChanged();
+
+    path_file = QUrl(path_file).toLocalFile();
+
+    QThread* snapshot_thread = QThread::create([this, path_file]() {
+        SnapshotQml loader(m_node, path_file);
+        bool result = loader.processPath();
+        if (!result) {
+            m_snapshot_loading = false;
+            Q_EMIT snapshotLoadingChanged();
+        } else {
+            m_snapshot_loaded = true;
+            Q_EMIT snapshotLoaded(result);
+            Q_EMIT snapshotLoadingChanged();
+        }
+    });
+
+    connect(snapshot_thread, &QThread::finished, snapshot_thread, &QThread::deleteLater);
+
+    snapshot_thread->start();
+}
+
+void NodeModel::setSnapshotProgress(double new_progress) {
+    if (new_progress != m_snapshot_progress) {
+        m_snapshot_progress = new_progress;
+        Q_EMIT snapshotProgressChanged();
+    }
+}
+
+void NodeModel::setHeadersSynced(bool new_synced) {
+    if (new_synced != m_headers_synced) {
+        m_headers_synced = new_synced;
+        Q_EMIT headersSyncedChanged();
+    }
+}
diff --git a/src/qml/models/nodemodel.h b/src/qml/models/nodemodel.h
index 8603c44d36..0c4180b269 100644
--- a/src/qml/models/nodemodel.h
+++ b/src/qml/models/nodemodel.h
@@ -34,6 +34,11 @@ class NodeModel : public QObject
     Q_PROPERTY(double verificationProgress READ verificationProgress NOTIFY verificationProgressChanged)
     Q_PROPERTY(bool pause READ pause WRITE setPause NOTIFY pauseChanged)
     Q_PROPERTY(bool faulted READ errorState WRITE setErrorState NOTIFY errorStateChanged)
+    Q_PROPERTY(double snapshotProgress READ snapshotProgress WRITE setSnapshotProgress NOTIFY snapshotProgressChanged)
+    Q_PROPERTY(bool snapshotLoading READ snapshotLoading NOTIFY snapshotLoadingChanged)
+    Q_PROPERTY(bool isSnapshotLoaded READ isSnapshotLoaded NOTIFY snapshotLoaded)
+    Q_PROPERTY(bool headersSynced READ headersSynced WRITE setHeadersSynced NOTIFY headersSyncedChanged)
+
 
 public:
     explicit NodeModel(interfaces::Node& node);
@@ -52,6 +57,12 @@ class NodeModel : public QObject
     void setPause(bool new_pause);
     bool errorState() const { return m_faulted; }
     void setErrorState(bool new_error);
+    bool isSnapshotLoaded() const { return m_snapshot_loaded; }
+    double snapshotProgress() const { return m_snapshot_progress; }
+    void setSnapshotProgress(double new_progress);
+    bool snapshotLoading() const { return m_snapshot_loading; }
+    bool headersSynced() const { return m_headers_synced; }
+    void setHeadersSynced(bool new_synced);
 
     Q_INVOKABLE float getTotalBytesReceived() const { return (float)m_node.getTotalBytesRecv(); }
     Q_INVOKABLE float getTotalBytesSent() const { return (float)m_node.getTotalBytesSent(); }
@@ -59,6 +70,8 @@ class NodeModel : public QObject
     Q_INVOKABLE void startNodeInitializionThread();
     Q_INVOKABLE void requestShutdown();
 
+    Q_INVOKABLE void snapshotLoadThread(QString path_file);
+
     void startShutdownPolling();
     void stopShutdownPolling();
 
@@ -80,7 +93,12 @@ public Q_SLOTS:
 
     void setTimeRatioList(int new_time);
     void setTimeRatioListInitial();
-
+    void initializationFinished();
+    void snapshotLoaded(bool result);
+    void snapshotProgressChanged();
+    void snapshotLoadingChanged();
+    void showProgress(const QString& title, int progress);
+    void headersSyncedChanged();
 protected:
     void timerEvent(QTimerEvent* event) override;
 
@@ -93,17 +111,21 @@ public Q_SLOTS:
     double m_verification_progress{0.0};
     bool m_pause{false};
     bool m_faulted{false};
-
+    double m_snapshot_progress{0.0};
     int m_shutdown_polling_timer_id{0};
-
+    int m_snapshot_timer_id{0};
+    bool m_snapshot_loading{false};
+    bool m_snapshot_loaded{false};
+    bool m_headers_synced{false};
     QVector<QPair<int, double>> m_block_process_time;
 
     interfaces::Node& m_node;
     std::unique_ptr<interfaces::Handler> m_handler_notify_block_tip;
     std::unique_ptr<interfaces::Handler> m_handler_notify_num_peers_changed;
-
+    std::unique_ptr<interfaces::Handler> m_handler_snapshot_load_progress;
     void ConnectToBlockTipSignal();
     void ConnectToNumConnectionsChangedSignal();
+    void ConnectToSnapshotLoadProgressSignal();
 };
 
 #endif // BITCOIN_QML_MODELS_NODEMODEL_H
diff --git a/src/qml/models/snapshotqml.cpp b/src/qml/models/snapshotqml.cpp
new file mode 100644
index 0000000000..6265aba417
--- /dev/null
+++ b/src/qml/models/snapshotqml.cpp
@@ -0,0 +1,40 @@
+// Copyright (c) 2024 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include <qml/models/snapshotqml.h>
+
+#include <node/utxo_snapshot.h>
+#include <sync.h>
+#include <util/fs.h>
+#include <util/fs_helpers.h>
+
+SnapshotQml::SnapshotQml(interfaces::Node& node, QString path)
+    : m_node(node), m_path(path) {}
+
+bool SnapshotQml::processPath()
+{
+    const fs::path path = fs::u8path(m_path.toStdString());
+    if (!fs::exists(path)) {
+        return false;
+    }
+
+    FILE* snapshot_file{fsbridge::fopen(path, "rb")};
+    AutoFile afile{snapshot_file};
+    if (afile.IsNull()) {
+        return false;
+    }
+
+    node::SnapshotMetadata metadata;
+    try {
+        afile >> metadata;
+    } catch (const std::exception& e) {
+        return false;
+    }
+
+    bool result = m_node.loadSnapshot(afile, metadata, false);
+    if (!result) {
+        return false;
+    }
+    return true;
+}
\ No newline at end of file
diff --git a/src/qml/models/snapshotqml.h b/src/qml/models/snapshotqml.h
new file mode 100644
index 0000000000..75e4758d7e
--- /dev/null
+++ b/src/qml/models/snapshotqml.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2024 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef BITCOIN_QML_MODELS_SNAPSHOTQML_H
+#define BITCOIN_QML_MODELS_SNAPSHOTQML_H
+
+#include <interfaces/handler.h>
+#include <interfaces/node.h>
+
+#include <QObject>
+
+class SnapshotQml : public QObject
+{
+   Q_OBJECT
+public:
+    SnapshotQml(interfaces::Node& node, QString path);
+
+    bool processPath();
+
+private:
+    interfaces::Node& m_node;
+    QString m_path;
+};
+
+#endif // BITCOIN_QML_MODELS_SNAPSHOTQML_H
diff --git a/src/qml/pages/settings/SettingsConnection.qml b/src/qml/pages/settings/SettingsConnection.qml
index d180fa2ff2..da5593c58d 100644
--- a/src/qml/pages/settings/SettingsConnection.qml
+++ b/src/qml/pages/settings/SettingsConnection.qml
@@ -12,6 +12,7 @@ Page {
     id: root
     signal back
     property bool onboarding: false
+    property bool snapshotImportCompleted: onboarding ? false : chainModel.isSnapshotActive
     background: null
     PageStack {
         id: stack
@@ -31,6 +32,9 @@ Page {
                 detailActive: true
                 detailItem: ConnectionSettings {
                     onNext: stack.push(proxySettings)
+                    onGotoSnapshot: stack.push(snapshotSettings)
+                    snapshotImportCompleted: root.snapshotImportCompleted
+                    onboarding: root.onboarding
                 }
 
                 states: [
@@ -87,5 +91,13 @@ Page {
                 onBack: stack.pop()
             }
         }
+        Component {
+            id: snapshotSettings
+            SettingsSnapshot {
+                onboarding: root.onboarding
+                snapshotImportCompleted: root.snapshotImportCompleted
+                onBack: stack.pop()
+            }
+        }
     }
 }
diff --git a/src/qml/pages/settings/SettingsSnapshot.qml b/src/qml/pages/settings/SettingsSnapshot.qml
new file mode 100644
index 0000000000..38f5529daf
--- /dev/null
+++ b/src/qml/pages/settings/SettingsSnapshot.qml
@@ -0,0 +1,38 @@
+// Copyright (c) 2024-present The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+import QtQuick.Layouts 1.15
+import "../../controls"
+import "../../components"
+
+Page {
+    signal back
+    property bool onboarding: false
+    property bool snapshotImportCompleted: onboarding ? false : chainModel.isSnapshotActive
+
+    id: root
+
+    background: null
+    implicitWidth: 450
+    leftPadding: 20
+    rightPadding: 20
+    topPadding: 30
+
+    header: NavigationBar2 {
+        leftItem: NavButton {
+            iconSource: "image://images/caret-left"
+            text: qsTr("Back")
+            onClicked: root.back()
+        }
+    }
+    SnapshotSettings {
+        width: Math.min(parent.width, 450)
+        anchors.horizontalCenter: parent.horizontalCenter
+        onboarding: root.onboarding
+        snapshotImportCompleted: root.snapshotImportCompleted
+        onBack: root.back()
+    }
+}
diff --git a/src/qml/res/icons/circle-file.png b/src/qml/res/icons/circle-file.png
new file mode 100644
index 0000000000..14a776e6d5
Binary files /dev/null and b/src/qml/res/icons/circle-file.png differ
diff --git a/src/qml/res/icons/circle-green-check.png b/src/qml/res/icons/circle-green-check.png
new file mode 100644
index 0000000000..25bb20e00f
Binary files /dev/null and b/src/qml/res/icons/circle-green-check.png differ
diff --git a/src/qml/res/icons/green-check.png b/src/qml/res/icons/green-check.png
new file mode 100644
index 0000000000..acce5e1a21
Binary files /dev/null and b/src/qml/res/icons/green-check.png differ
diff --git a/src/qml/res/src/circle-file.svg b/src/qml/res/src/circle-file.svg
new file mode 100644
index 0000000000..d8af3949d8
--- /dev/null
+++ b/src/qml/res/src/circle-file.svg
@@ -0,0 +1,18 @@
+<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80" width="80" height="80">
+	<title>circle-file-svg</title>
+	<defs>
+		<clipPath clipPathUnits="userSpaceOnUse" id="cp1">
+			<path d="m40 0c22.09 0 40 17.91 40 40 0 22.09-17.91 40-40 40-22.09 0-40-17.91-40-40 0-22.09 17.91-40 40-40z"/>
+		</clipPath>
+	</defs>
+	<style>
+		.s0 { opacity: .3;fill: #3ca3de }
+		.s1 { fill: #3ca3de }
+	</style>
+	<g id="Clip-Path" clip-path="url(#cp1)">
+		<g>
+			<path class="s0" d="m40 80c-22.1 0-40-17.9-40-40 0-22.1 17.9-40 40-40 22.1 0 40 17.9 40 40 0 22.1-17.9 40-40 40z"/>
+			<path fill-rule="evenodd" class="s1" d="m54 32.8v22.7c0 2-1.6 3.6-3.5 3.6h-21c-1.9 0-3.5-1.6-3.5-3.6v-31c0-2 1.6-3.6 3.5-3.6h12.8zm-14-8.1v9.9c0 0.3 0.3 0.6 0.6 0.6h9.7c0.5 0 0.8-0.6 0.4-1l-9.7-9.9c-0.3-0.4-1-0.1-1 0.4z"/>
+		</g>
+	</g>
+</svg>
\ No newline at end of file
diff --git a/src/qml/res/src/circle-green-check.svg b/src/qml/res/src/circle-green-check.svg
new file mode 100644
index 0000000000..d56c175fd4
--- /dev/null
+++ b/src/qml/res/src/circle-green-check.svg
@@ -0,0 +1,18 @@
+<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80" width="80" height="80">
+	<title>Circle arrow up-svg</title>
+	<defs>
+		<clipPath clipPathUnits="userSpaceOnUse" id="cp1">
+			<path d="m40 0c22.09 0 40 17.91 40 40 0 22.09-17.91 40-40 40-22.09 0-40-17.91-40-40 0-22.09 17.91-40 40-40z"/>
+		</clipPath>
+	</defs>
+	<style>
+		.s0 { opacity: .3;fill: #36b46b }
+		.s1 { fill: none;stroke: #27ae60;stroke-linecap: round;stroke-linejoin: round;stroke-width: 1.3 }
+	</style>
+	<g id="Clip-Path" clip-path="url(#cp1)">
+		<g>
+			<path class="s0" d="m40 80c-22.1 0-40-17.9-40-40 0-22.1 17.9-40 40-40 22.1 0 40 17.9 40 40 0 22.1-17.9 40-40 40z"/>
+			<path fill-rule="evenodd" class="s1" d="m29.3 42l8.5 7.3 12.2-18.6"/>
+		</g>
+	</g>
+</svg>
\ No newline at end of file
diff --git a/src/qml/res/src/green-check.svg b/src/qml/res/src/green-check.svg
new file mode 100644
index 0000000000..95f7c80ead
--- /dev/null
+++ b/src/qml/res/src/green-check.svg
@@ -0,0 +1,9 @@
+<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30" width="30" height="30">
+	<title>green-check-svg</title>
+	<style>
+		.s0 { fill: #27ae60 }
+		.s1 { fill: none;stroke: #ffffff;stroke-linecap: round;stroke-linejoin: round;stroke-width: 1.7 }
+	</style>
+	<path class="s0" d="m15 0c8.3 0 15 6.7 15 15 0 8.3-6.7 15-15 15-8.3 0-15-6.7-15-15 0-8.3 6.7-15 15-15z"/>
+	<path fill-rule="evenodd" class="s1" d="m8.1 16.2l5.2 4.6 7.6-11.6"/>
+</svg>
\ No newline at end of file
diff --git a/src/validation.cpp b/src/validation.cpp
index ed9889d9dd..c67cb91178 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -5261,6 +5261,10 @@ bool ChainstateManager::PopulateAndValidateSnapshot(
         --coins_left;
         ++coins_processed;
 
+        // Show Snapshot Loading progress
+        double progress = static_cast<double>(coins_processed) / static_cast<double>(coins_count);
+        GetNotifications().snapshotLoadProgress(progress);
+
         if (coins_processed % 1000000 == 0) {
             LogPrintf("[snapshot] %d coins loaded (%.2f%%, %.2f MB)\n",
                 coins_processed,