Sanity Client 403 Error in SvelteKit with Flashing Content

18 replies
Last updated: Jan 27, 2026
Hi -- any tips on dealing w/ 403 errors using the sanity client in a Sveltekit project?
I have this
page.ts

import type { PageLoad } from './$types';
import sanityClient from '../../lib/sanity'


// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const load = (async ({ params }) => {
  const data = await sanityClient.fetch(`*[_type=="project"]`);
    return {
      name: "Rob",
      projects: data
    };
 }) satisfies PageLoad;
with this
page.svelte

<script lang="ts">
	import type { PageData } from './$types';

	export let data: PageData;
	const { name, projects } = data;
</script>

<h1>{name}</h1>
{#if projects}
	<pre>
		{JSON.stringify(projects, null, 2)}
	</pre>
{:else}
	<p>Your data will show up here when you've configured everything correctly</p>
{/if}
it does momentarily flash the content, then it throws an error. I can fetch dummy data no problem.
AI Update

The 403 error you're seeing in your SvelteKit project is almost certainly a CORS (Cross-Origin Resource Sharing) configuration issue. The fact that content "flashes" briefly suggests your query works initially server-side, but fails when SvelteKit tries to re-fetch it client-side.

The Problem

SvelteKit's default behavior is to run load functions on both the server (SSR) and client (browser). The server-side fetch works fine, but when the page hydrates or navigates client-side, the browser makes a direct request to Sanity's API - and that's where CORS restrictions kick in.

The Solution

You need to add your development and production domains to your Sanity project's CORS origins:

  1. Go to manage.sanity.io
  2. Select your project
  3. Navigate to Settings → API → CORS Origins
  4. Click Add CORS origin
  5. Add your domains:
    • http://localhost:5173 (or whatever port your SvelteKit dev server uses)
    • Your production domain (e.g., https://yourdomain.com)
  6. Check "Allow credentials" if you need authentication

Additional SvelteKit-Specific Tips

Option 1: Force server-side only (Quick fix)

Add this to your page.ts to prevent client-side re-fetching:

export const ssr = true;
export const csr = false;

Option 2: Use SvelteKit's server load (Recommended)

Rename page.ts to +page.server.ts. This ensures the load function only runs server-side, bypassing CORS entirely:

// +page.server.ts
import type { PageServerLoad } from './$types';
import sanityClient from '../../lib/sanity';

export const load = (async ({ params }) => {
  const data = await sanityClient.fetch(`*[_type=="project"]`);
  return {
    name: "Rob",
    projects: data
  };
}) satisfies PageServerLoad;

Option 3: Proxy through SvelteKit (Most robust)

Create an API endpoint in SvelteKit to proxy Sanity requests, keeping all external API calls server-side. This is especially useful for authenticated requests.

Verify Your Client Configuration

Make sure your Sanity client is properly configured with all required fields:

// lib/sanity.ts
import { createClient } from '@sanity/client';

export default createClient({
  projectId: 'your-project-id',
  dataset: 'production',
  apiVersion: '2024-01-01',
  useCdn: true, // `false` if you need fresh data
});

The server-side load approach (+page.server.ts) is generally the best practice for SvelteKit + Sanity since it keeps your data fetching server-side, improves performance, and avoids CORS issues entirely.

Show original thread
18 replies

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?