The RecipeScrape API: A Complete Guide to Cooking with Code
Every endpoint, every parameter, every response shape — a practical walkthrough of the RecipeScrape JSON API with curl, JavaScript, and Python examples.
The RecipeScrape API is a public JSON API served from https://recipescrape.vercel.app/api/v1/. All endpoints return JSON. Every recipe response includes sourceUrl and sourceSite for attribution — attribution is non-negotiable.
Base URL
https://recipescrape.vercel.app/api/v1/---
GET /api/v1/recipes
List recipes with full-text search, filters, and pagination. This is the main endpoint for searching the recipe collection.
Parameters
| Name | Type | Description |
|---|---|---|
q | string | Full-text search query across title + description |
source | string | Filter by source site (e.g. recipetineats, allrecipes) |
cuisine | string | Filter by cuisine (e.g. italian, mexican) |
category | string | Filter by category (e.g. Dinner, Dessert) |
Response shape
{
"total": 142,
"limit": 20,
"offset": 0,
"results": [
{
"id": "a1b2c3d4-...",
"slug": "creamy-garlic-parmesan-pasta",
"title": "Creamy Garlic Parmesan Pasta",
"description": "A rich and creamy pasta dish...",
"sourceUrl": "https://www.recipetineats.com/creamy-garlic-parmesan-pasta/",
"sourceSite": "recipetineats",
"imageUrl": "https://...",
"author": "Nagi Maehashi",
"cuisine": "Italian",
"category": "Dinner",
"keywords": ["pasta", "garlic", "creamy", "quick"],
"servings": 4,
"prepTimeMinutes": 10,
"cookTimeMinutes": 15,
"totalTimeMinutes": 25,
"difficulty": "easy",
"ingredients": [
{ "name": "fettuccine", "quantity": "12", "unit": "oz", "notes": null }
],
"instructions": [
{ "step": 1, "text": "Cook pasta according to package directions." }
],
"nutrition": {
"calories": 520,
"protein_g": 18,
"fat_g": 28,
"carbs_g": 48,
"fiber_g": 2
},
"rating": 4.8,
"reviewCount": 1204,
"scrapedAt": "2026-06-01T12:00:00Z"
}
]
}Examples
Search for chicken recipes under 30 minutes:
curl "https://recipescrape.vercel.app/api/v1/recipes?q=chicken&max_time=30&limit=5"JavaScript:
const res = await fetch(
"https://recipescrape.vercel.app/api/v1/recipes?q=chicken&max_time=30&limit=5"
);
const data = await res.json();
console.log(`${data.total} recipes found`);
data.results.forEach(r => console.log(r.title));Python:
import httpx
res = httpx.get("https://recipescrape.vercel.app/api/v1/recipes", params={
"q": "chicken",
"max_time": 30,
"limit": 5,
})
data = res.json()
print(f"{data['total']} recipes found")
for r in data["results"]:
print(r["title"])Pagination
The API uses offset-based pagination. To get the next page, add offset equal to the current page size:
curl "https://recipescrape.vercel.app/api/v1/recipes?limit=20&offset=20"
curl "https://recipescrape.vercel.app/api/v1/recipes?limit=20&offset=40"Combining filters
All filter parameters compound with AND logic:
# Italian dinner recipes under 45 minutes
curl "https://recipescrape.vercel.app/api/v1/recipes?cuisine=italian&category=Dinner&max_time=45"---
GET /api/v1/recipes/random
Get a random recipe. Optionally filter by source site.
Parameters
| Name | Type | Description |
|---|---|---|
source | string | Optional source site filter |
Example
curl "https://recipescrape.vercel.app/api/v1/recipes/random?source=allrecipes"JavaScript:
const res = await fetch(
"https://recipescrape.vercel.app/api/v1/recipes/random"
);
const recipe = await res.json();
console.log(`Try making: ${recipe.title}`);Returns a single recipe object or 404 if no recipes match.
---
GET /api/v1/recipes/:slug
Get a single recipe by its URL slug.
Parameters
| Name | Type | Description |
|---|---|---|
slug | string | URL slug (from the recipe's slug field) |
Example
curl "https://recipescrape.vercel.app/api/v1/recipes/creamy-garlic-parmesan-pasta"JavaScript:
const slug = "creamy-garlic-parmesan-pasta";
const res = await fetch(
`https://recipescrape.vercel.app/api/v1/recipes/${slug}`
);
const recipe = await res.json();
console.log(recipe.ingredients);Returns a single recipe object or 404 if not found. Slugs are unique and URL-safe.
---
GET /api/v1/sources
List all scraped source sites with recipe counts and last-scraped timestamps. Useful for building a source directory or populating a filter dropdown.
Response
[
{ "site": "allrecipes", "count": 2183, "lastScraped": "2026-06-23T03:00:00Z" },
{ "site": "foodnetwork", "count": 954, "lastScraped": "2026-06-23T03:00:00Z" },
{ "site": "recipetineats", "count": 1247, "lastScraped": "2026-06-23T03:00:00Z" },
{ "site": "simplyrecipes", "count": 876, "lastScraped": "2026-06-23T03:00:00Z" }
]Example
curl "https://recipescrape.vercel.app/api/v1/sources"Use the returned site values with the source parameter on the recipes endpoint:
curl "https://recipescrape.vercel.app/api/v1/recipes?source=recipetineats&limit=5"---
GET /api/v1/categories
List all distinct category values, sorted alphabetically.
Response
["Appetizer", "Breakfast", "Dessert", "Dinner", "Drinks", "Lunch", "Salad", "Side Dish", "Snack", "Soup"]Example
curl "https://recipescrape.vercel.app/api/v1/categories"Use values with ?category= on the recipes endpoint:
curl "https://recipescrape.vercel.app/api/v1/recipes?category=Dessert&limit=10"---
GET /api/v1/cuisines
List all distinct cuisine values, sorted alphabetically.
Response
["American", "British", "Chinese", "French", "Indian", "Italian", "Japanese", "Mexican", "Middle Eastern", "Thai", "Vietnamese"]Example
curl "https://recipescrape.vercel.app/api/v1/cuisines"---
GET /api/v1/health
Quick health check. Returns server status, total recipe count, and the last scrape timestamp.
Response
{
"status": "ok",
"recipeCount": 7166,
"lastScrape": "2026-06-24T03:00:00Z"
}Example
curl "https://recipescrape.vercel.app/api/v1/health"---
Building Something with the API
Here's a complete example in Node.js that fetches a random Italian recipe and logs the ingredients:
const BASE = "https://recipescrape.vercel.app/api/v1";
async function getRandomItalianRecipe() {
const res = await fetch(`${BASE}/recipes/random?source=allrecipes`);
if (!res.ok) throw new Error("No recipe found");
return res.json();
}
async function getRecipeDetail(slug) {
const res = await fetch(`${BASE}/recipes/${slug}`);
if (!res.ok) throw new Error("Recipe not found");
return res.json();
}
const random = await getRandomItalianRecipe();
const detail = await getRecipeDetail(random.slug);
console.log(`Recipe: ${detail.title}`);
console.log(`By: ${detail.author}`);
console.log(`Time: ${detail.totalTimeMinutes} minutes`);
console.log("\nIngredients:");
detail.ingredients.forEach((ing) => {
console.log(` ${ing.quantity} ${ing.unit} ${ing.name}`);
});And the same thing in Python:
import httpx
BASE = "https://recipescrape.vercel.app/api/v1"
res = httpx.get(f"{BASE}/recipes/random")
random = res.json()
res = httpx.get(f"{BASE}/recipes/{random['slug']}")
detail = res.json()
print(f"Recipe: {detail['title']}")
print(f"By: {detail['author']}")
print(f"Time: {detail['totalTimeMinutes']} minutes")
print("\nIngredients:")
for ing in detail['ingredients']:
print(f" {ing['quantity']} {ing['unit']} {ing['name']}")Response Fields Reference
Every recipe object returned by the API has these fields:
| Field | Type | Always present |
|---|---|---|
id | string (UUID) | yes |
slug | string | yes |
title | string | yes |
description | string or null | no |
sourceUrl | string | yes |
sourceSite | string | yes |
The nutrition object, when present, contains calories, protein_g, fat_g, carbs_g, and fiber_g — all numbers or null.