How to use GROQ queries with filters in Sanity HTTP API fetch requests?

4 replies
Last updated: Jan 28, 2026
Hi guys. How would I fetch data without sanity client with queries and filter? I know that this works const query = `*[_type=="tweet"]`; const url = `https://<projectId>.
api.sanity.io/v1/data/query/development?query=${query} `; const tweets = await fetch(url).then(res => res.json());

but how would I use this query with filtering
const currentUserTweetsQuery =
*[_type == "tweet" && userId == '${userId}] | order(_createdAt desc)
? (this works via sanity online and via sanity client fetch)into const url = `https://<projectId>.
api.sanity.io/v1/data/query/development?query=${currentUserTweetsQuery} `;const tweets = await fetch(url).then(res => res.json());

Thanks in advance for the help! New to sanity.
AI Update

You're on the right track! The issue is that when you use the HTTP API directly with fetch, you need to properly URL encode your GROQ query, especially the && operator and any quotes. Here's how to fix your query:

// Your GROQ query
const currentUserTweetsQuery = `*[_type == "tweet" && userId == '${userId}'] | order(_createdAt desc)`;

// URL encode it before adding to the URL
const encodedQuery = encodeURIComponent(currentUserTweetsQuery);

const url = `https://<projectId>.api.sanity.io/v1/data/query/development?query=${encodedQuery}`;
const tweets = await fetch(url).then(res => res.json());

The key here is using encodeURIComponent() which will properly encode special characters like:

  • && becomes %26%26
  • Spaces become %20
  • Quotes and brackets get encoded too

However, there's a better approach: Use GROQ parameters instead of string interpolation. This is safer and cleaner:

// Define query with parameter
const query = `*[_type == "tweet" && userId == $userId] | order(_createdAt desc)`;

// URL encode the query
const encodedQuery = encodeURIComponent(query);

// Add the parameter as a separate URL parameter
const url = `https://<projectId>.api.sanity.io/v1/data/query/development?query=${encodedQuery}&$userId="${userId}"`;
const tweets = await fetch(url).then(res => res.json());

Even better: Consider using the @sanity/client library instead of raw fetch. It handles all the encoding automatically and is much cleaner:

import {createClient} from '@sanity/client'

const client = createClient({
  projectId: '<projectId>',
  dataset: 'development',
  apiVersion: '2024-01-01',
  useCdn: false
})

const tweets = await client.fetch(
  `*[_type == "tweet" && userId == $userId] | order(_createdAt desc)`,
  { userId: userId }
)

The client approach is recommended because it automatically handles URL encoding, parameter escaping, and prevents potential GROQ injection issues that can occur with string interpolation. As noted in the GROQ Parameters documentation, using parameters with $ syntax makes queries safer and more maintainable than string concatenation.

Show original thread
4 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?