diff --git a/.changeset/calm-fireants-hug.md b/.changeset/calm-fireants-hug.md
new file mode 100644
index 000000000000..b4ade6d2f778
--- /dev/null
+++ b/.changeset/calm-fireants-hug.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+fix: only preload links that have a different URL than the current page
diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js
index cd5288dbb0d4..715ef84cff9e 100644
--- a/packages/kit/src/runtime/client/client.js
+++ b/packages/kit/src/runtime/client/client.js
@@ -1543,7 +1543,10 @@ function setup_preload() {
const options = get_router_options(a);
- if (!options.reload) {
+ // we don't want to preload data for a page we're already on
+ const same_url = url && current.url.pathname + current.url.search === url.pathname + url.search;
+
+ if (!options.reload && !same_url) {
if (priority <= options.preload_data) {
const intent = get_navigation_intent(url, false);
if (intent) {
diff --git a/packages/kit/test/apps/basics/src/routes/routing/hashes/a/+page.svelte b/packages/kit/test/apps/basics/src/routes/routing/hashes/a/+page.svelte
index 7ac5f9c2a32b..7715b3d2458d 100644
--- a/packages/kit/test/apps/basics/src/routes/routing/hashes/a/+page.svelte
+++ b/packages/kit/test/apps/basics/src/routes/routing/hashes/a/+page.svelte
@@ -2,3 +2,6 @@
hash link
b
replace state
+
+/routing/hashes/a
+#preload
diff --git a/packages/kit/test/apps/basics/test/cross-platform/client.test.js b/packages/kit/test/apps/basics/test/cross-platform/client.test.js
index b8f485fc228d..7f57086b4048 100644
--- a/packages/kit/test/apps/basics/test/cross-platform/client.test.js
+++ b/packages/kit/test/apps/basics/test/cross-platform/client.test.js
@@ -615,6 +615,19 @@ test.describe('Prefetching', () => {
await expect(page.locator('h1')).not.toHaveText('Oopsie');
});
+ test('same route hash links work more than once', async ({ page, clicknav, baseURL }) => {
+ await page.goto('/routing/hashes/a');
+
+ await clicknav('[href="#preload"]');
+ await expect(page.url()).toBe(`${baseURL}/routing/hashes/a#preload`);
+
+ await clicknav('[href="/routing/hashes/a"]');
+ await expect(page.url()).toBe(`${baseURL}/routing/hashes/a`);
+
+ await clicknav('[href="#preload"]');
+ await expect(page.url()).toBe(`${baseURL}/routing/hashes/a#preload`);
+ });
+
test('does not rerun load on calls to duplicate preload hash route', async ({ app, page }) => {
await page.goto('/routing/a');