diff --git a/src/syrupy/__init__.py b/src/syrupy/__init__.py
index d351be5f..3c42f7fe 100644
--- a/src/syrupy/__init__.py
+++ b/src/syrupy/__init__.py
@@ -146,14 +146,15 @@ def pytest_collection_finish(session: Any) -> None:
     session.config._syrupy.select_items(session.items)
 
 
-def pytest_runtest_logfinish(nodeid: str) -> None:
+def pytest_runtest_logreport(report: pytest.TestReport) -> None:
     """
-    At the end of running the runtest protocol for a single item.
-    https://docs.pytest.org/en/latest/reference.html#_pytest.hookspec.pytest_runtest_logfinish
+    After each of the setup, call and teardown runtest phases of an item.
+    https://docs.pytest.org/en/8.0.x/reference/reference.html#pytest.hookspec.pytest_runtest_logreport
     """
     global _syrupy
-    if _syrupy:
-        _syrupy.ran_item(nodeid)
+    # The outcome will be passed in the teardown phase even if skipped
+    if _syrupy and report.when != "teardown":
+        _syrupy.ran_item(report.nodeid, report.outcome)
 
 
 @pytest.hookimpl(tryfirst=True)
diff --git a/src/syrupy/report.py b/src/syrupy/report.py
index 5eaa4b66..7d07e14c 100644
--- a/src/syrupy/report.py
+++ b/src/syrupy/report.py
@@ -46,6 +46,7 @@
     import pytest
 
     from .assertion import SnapshotAssertion
+    from .session import ItemStatus
 
 
 @dataclass
@@ -59,7 +60,7 @@ class SnapshotReport:
     # Initial arguments to the report
     base_dir: Path
     collected_items: Set["pytest.Item"]
-    selected_items: Dict[str, bool]
+    selected_items: Dict[str, "ItemStatus"]
     options: "argparse.Namespace"
     assertions: List["SnapshotAssertion"]
 
@@ -196,6 +197,14 @@ def num_unused(self) -> int:
     def selected_all_collected_items(self) -> bool:
         return self._collected_items_by_nodeid.keys() == self.selected_items.keys()
 
+    @property
+    def skipped_items(self) -> Iterator["pytest.Item"]:
+        return (
+            self._collected_items_by_nodeid[nodeid]
+            for nodeid in self.selected_items
+            if self.selected_items[nodeid].value == "skipped"
+        )
+
     @property
     def ran_items(self) -> Iterator["pytest.Item"]:
         return (
@@ -230,7 +239,13 @@ def unused(self) -> "SnapshotCollections":
             if self.selected_all_collected_items and not any(provided_nodes):
                 # All collected tests were run and files were not filtered by ::node
                 # therefore the snapshot collection file at this location can be deleted
-                unused_snapshots = {*unused_snapshot_collection}
+                unused_snapshots = {
+                    snapshot
+                    for snapshot in unused_snapshot_collection
+                    if not self._skipped_items_match_name(
+                        snapshot_location=snapshot_location, snapshot_name=snapshot.name
+                    )
+                }
                 mark_for_removal = snapshot_location not in self.used
             else:
                 unused_snapshots = {
@@ -244,6 +259,9 @@ def unused(self) -> "SnapshotCollections":
                         snapshot_name=snapshot.name,
                         provided_nodes=provided_nodes,
                     )
+                    and not self._skipped_items_match_name(
+                        snapshot_location=snapshot_location, snapshot_name=snapshot.name
+                    )
                 }
                 mark_for_removal = False
 
@@ -451,6 +469,21 @@ def _ran_items_match_name(self, snapshot_location: str, snapshot_name: str) -> b
                 return True
         return False
 
+    def _skipped_items_match_name(
+        self, snapshot_location: str, snapshot_name: str
+    ) -> bool:
+        """
+        Check that a snapshot name should be treated as skipped by the current session
+        This being true means that it will not be deleted even if the it is unused
+        """
+        for item in self.skipped_items:
+            location = PyTestLocation(item)
+            if location.matches_snapshot_location(
+                snapshot_location
+            ) and location.matches_snapshot_name(snapshot_name):
+                return True
+        return False
+
     def _selected_items_match_name(
         self, snapshot_location: str, snapshot_name: str
     ) -> bool:
diff --git a/src/syrupy/session.py b/src/syrupy/session.py
index 6b612145..9ec6aca1 100644
--- a/src/syrupy/session.py
+++ b/src/syrupy/session.py
@@ -3,6 +3,7 @@
     dataclass,
     field,
 )
+from enum import Enum
 from pathlib import Path
 from typing import (
     TYPE_CHECKING,
@@ -11,6 +12,7 @@
     Dict,
     Iterable,
     List,
+    Literal,
     Optional,
     Set,
     Tuple,
@@ -37,6 +39,13 @@
     from .extensions.base import AbstractSyrupyExtension
 
 
+class ItemStatus(Enum):
+    NOT_RUN = False
+    PASSED = "passed"
+    FAILED = "failed"
+    SKIPPED = "skipped"
+
+
 @dataclass
 class SnapshotSession:
     pytest_session: "pytest.Session"
@@ -45,7 +54,7 @@ class SnapshotSession:
     # All the collected test items
     _collected_items: Set["pytest.Item"] = field(default_factory=set)
     # All the selected test items. Will be set to False until the test item is run.
-    _selected_items: Dict[str, bool] = field(default_factory=dict)
+    _selected_items: Dict[str, ItemStatus] = field(default_factory=dict)
     _assertions: List["SnapshotAssertion"] = field(default_factory=list)
     _extensions: Dict[str, "AbstractSyrupyExtension"] = field(default_factory=dict)
 
@@ -97,7 +106,9 @@ def collect_items(self, items: List["pytest.Item"]) -> None:
 
     def select_items(self, items: List["pytest.Item"]) -> None:
         for item in self.filter_valid_items(items):
-            self._selected_items[getattr(item, "nodeid")] = False  # noqa: B009
+            self._selected_items[getattr(item, "nodeid")] = (  # noqa: B009
+                ItemStatus.NOT_RUN
+            )
 
     def start(self) -> None:
         self.report = None
@@ -107,9 +118,11 @@ def start(self) -> None:
         self._extensions = {}
         self._locations_discovered = defaultdict(set)
 
-    def ran_item(self, nodeid: str) -> None:
+    def ran_item(
+        self, nodeid: str, outcome: Literal["passed", "skipped", "failed"]
+    ) -> None:
         if nodeid in self._selected_items:
-            self._selected_items[nodeid] = True
+            self._selected_items[nodeid] = ItemStatus(outcome)
 
     def finish(self) -> int:
         exitstatus = 0
diff --git a/tests/integration/test_snapshot_skipped.py b/tests/integration/test_snapshot_skipped.py
new file mode 100644
index 00000000..c985bf80
--- /dev/null
+++ b/tests/integration/test_snapshot_skipped.py
@@ -0,0 +1,74 @@
+import pytest
+
+
+@pytest.fixture
+def testcases():
+    return {
+        "used": (
+            """
+            def test_used(snapshot):
+                assert snapshot == 'used'
+            """
+        ),
+        "raise-skipped": (
+            """
+            import pytest
+            def test_skipped(snapshot):
+                pytest.skip("Skipping...")
+                assert snapshot == 'unused'
+            """
+        ),
+        "mark-skipped": (
+            """
+            import pytest
+            @pytest.mark.skip
+            def test_skipped(snapshot):
+                assert snapshot == 'unused'
+            """
+        ),
+        "not-skipped": (
+            """
+            def test_skipped(snapshot):
+                assert snapshot == 'unused'
+            """
+        ),
+    }
+
+
+@pytest.fixture
+def run_testcases(testdir, testcases):
+    pyfile_content = "\n\n".join([testcases["used"], testcases["not-skipped"]])
+    testdir.makepyfile(test_file=pyfile_content)
+    result = testdir.runpytest("-v", "--snapshot-update")
+    result.stdout.re_match_lines(r"2 snapshots generated\.")
+    return testdir, testcases
+
+
+def test_mark_skipped_snapshots(run_testcases):
+    testdir, testcases = run_testcases
+    pyfile_content = "\n\n".join([testcases["used"], testcases["mark-skipped"]])
+    testdir.makepyfile(test_file=pyfile_content)
+
+    result = testdir.runpytest("-v")
+    result.stdout.re_match_lines(r"1 snapshot passed\.$")
+    assert result.ret == 0
+
+
+def test_raise_skipped_snapshots(run_testcases):
+    testdir, testcases = run_testcases
+    pyfile_content = "\n\n".join([testcases["used"], testcases["raise-skipped"]])
+    testdir.makepyfile(test_file=pyfile_content)
+
+    result = testdir.runpytest("-v")
+    result.stdout.re_match_lines(r"1 snapshot passed\.$")
+    assert result.ret == 0
+
+
+def test_skipped_snapshots_update(run_testcases):
+    testdir, testcases = run_testcases
+    pyfile_content = "\n\n".join([testcases["used"], testcases["raise-skipped"]])
+    testdir.makepyfile(test_file=pyfile_content)
+
+    result = testdir.runpytest("-v", "--snapshot-update")
+    result.stdout.re_match_lines(r"1 snapshot passed\.$")
+    assert result.ret == 0