Courses/Streamlit: 20 Real Apps/Module 5: APIs & Automation
Module 5 · Lesson 325 minBeginner

Project 16: Recipe Finder

What you'll build
Search real recipes by ingredients through a second real-world API.

Introduction

This project shows you how to build a Recipe Finder web app using Python, Streamlit, and the Spoonacular API. Enter ingredients you have at home and the app will find recipes you can make right now. This app and the weather app share the same API-request skeleton — learn one and you know both.

Prerequisites

  • Python 3.8+python.org
  • Libraries:
  • code
    pip install streamlit requests
  • Spoonacular API Key — Sign up for free at spoonacular.com/food-api and grab your API key from the dashboard.
  • Step 1: Create the Script

    Create recipe_finder.py and paste the following:

    code
    import streamlit as st
    import requests
    
    st.set_page_config(page_title="Recipe Finder", page_icon="🍳")
    st.title("🍳 Recipe Finder")
    st.write("Enter ingredients you have and discover recipes you can make!")
    
    API_KEY = "YOUR_SPOONACULAR_API_KEY"
    
    ingredients = st.text_input(
        "Enter ingredients (comma-separated):",
        placeholder="e.g. chicken, tomato, garlic"
    )
    num_results = st.slider("Number of recipes", 1, 10, 5)
    
    if st.button("Find Recipes") and ingredients:
        url = (
            f"https://api.spoonacular.com/recipes/findByIngredients"
            f"?apiKey={API_KEY}&ingredients={ingredients}&number={num_results}"
        )
        response = requests.get(url)
        if response.status_code == 200:
            recipes = response.json()
            if recipes:
                for recipe in recipes:
                    with st.expander(f"🍽️ {recipe['title']}"):
                        col1, col2 = st.columns([1, 2])
                        with col1:
                            st.image(recipe['image'], use_column_width=True)
                        with col2:
                            used = [i['name'] for i in recipe['usedIngredients']]
                            missed = [i['name'] for i in recipe['missedIngredients']]
                            st.write(f"**✅ Used:** {', '.join(used)}")
                            st.write(f"**🛒 Missing:** {', '.join(missed)}")
            else:
                st.info("No recipes found. Try different ingredients!")
        else:
            st.error("API error — please check your API key.")

    Step 2: Add Your API Key

    Replace YOUR_SPOONACULAR_API_KEY with the key from your Spoonacular dashboard.

    Step 3: Run the App

    code
    streamlit run recipe_finder.py

    Step 4: Use the App

    Enter ingredients separated by commas (e.g. chicken, tomato, garlic), adjust the slider for how many recipes to show, and click Find Recipes. Each result is collapsible and shows the recipe image alongside used and missing ingredients.

    How It Works

    The flow is: read comma-separated ingredients from st.text_input, split and strip them into a list, then call the Spoonacular complexSearch endpoint with includeIngredients. The API returns matching recipe IDs and titles; a second call to the information endpoint per recipe fetches details like image and used/missed ingredient counts.

    Two design choices matter. First, debouncing via button — the search only fires on st.button("Find Recipes"), so typing does not spam the API. Second, defensive parsing — every field is read with .get() because recipe data is inconsistently populated.

    Rendering uses st.columns(3) for a card grid, with st.image() and a markdown link per card. If you want to visualize nutrition data from the response, the charting patterns from the Pandas dashboard tutorial drop straight in.

    Key Concepts

  • `requests.get(url)` — Calls the Spoonacular API and returns recipe data.
  • `st.expander()` — Creates a collapsible card for each recipe result.
  • `st.image()` — Renders the recipe thumbnail image.
  • `st.slider()` — Lets the user control how many results to fetch.
  • What to Try Next

  • Filter by diet (vegetarian, vegan, gluten-free) using extra API parameters.
  • Show nutritional info using the Spoonacular nutrition endpoint.
  • Let users save favourite recipes with st.session_state.
  • Common Errors & Fixes

  • 401/403 from Spoonacular — free-tier keys activate slowly and have daily quotas (about 150 calls/day). Cache results with @st.cache_data to stretch the quota.
  • No recipes found — too many ingredients at once over-constrains the search. Try 2-3 core ingredients and add more only if needed.
  • `requests.exceptions.MissingSchema` — the base URL lost its https://, usually from a stray quote when concatenating the query string. Use the params= argument instead of string building.
  • Images fail to load — Spoonacular serves images over HTTPS with short-lived URLs; pass headers or re-fetch rather than caching image URLs long-term.
  • Duplicate recipes in results — the API returns the same dish for overlapping ingredient sets; deduplicate on recipe id before rendering the grid.
  • Ingredients input breaks on trailing comma"eggs, milk," produces an empty string in the list; filter with [i.strip() for i in raw.split(",") if i.strip()].
  • FAQ

    Is the Spoonacular API free?

    There is a free tier (~150 calls/day) which is enough for personal use. Paid tiers raise the quota.

    Can I filter by diet (vegan, gluten-free)?

    Yes — add diet=vegan or intolerances=gluten as query parameters; the API supports dozens of filters.

    How do I show full instructions?

    Call the /recipes/{id}/analyzedInstructions endpoint and render the returned steps as a numbered st.markdown list.

    Can I search by dish name instead of ingredients?

    Yes — the same API's query parameter accepts names like "pasta"; swap the parameter and keep the identical rendering code.

    Adapted from: Recipe Finder using Python and Streamlit

    Checkpoint
    Entering ingredients returns recipe cards with images.
    What you learned
    • Query parameters and API filters
    • Button-gated requests
    • Column card grids