Khan Academy's public API is largely deprecated and provides limited programmatic access. The recommended approach for Lovable is to embed Khan Academy content using oEmbed video URLs and content library links, routed through a lightweight Edge Function. You can build educational content viewers, progress-tracking dashboards, and curated learning paths by combining Khan Academy's public video URLs with your own Supabase database for user progress tracking.
Build educational content viewers with Khan Academy's public content
Khan Academy's public API was never fully open and has been progressively deprecated since 2018. As of 2026, programmatic access to courses, exercises, and user data requires a partnership agreement with Khan Academy — it is not available to independent developers. What remains publicly accessible are the video URLs themselves (hosted on YouTube and Khan Academy's CDN) and the oEmbed endpoint for embedding individual videos.
This means the practical integration strategy for Lovable is different from most API integrations: instead of querying Khan Academy for data, you build your own data layer. You curate the Khan Academy content URLs you want to feature, store them in your Supabase database, and track user progress internally. The Khan Academy content plays via embedded YouTube players or Khan Academy's own player, but everything around it — user accounts, progress tracking, completion marking, learning paths — lives in your Lovable app.
This approach has a genuine advantage: you are not dependent on Khan Academy's API availability, rate limits, or future deprecation decisions. Your app's data is fully under your control. The trade-off is that you need to manually curate content URLs rather than pulling them dynamically from an API. For educational apps targeting specific subject areas or grade levels, this manual curation often produces better results than algorithmic content selection anyway — teachers know better than algorithms which Khan Academy videos actually help students.
Integration method
Khan Academy's public API is deprecated and no longer supports full programmatic access. The practical integration pattern for Lovable is to use Khan Academy's publicly accessible content library URLs and oEmbed video endpoint to embed content, with an Edge Function handling any server-side URL resolution or metadata fetching. User progress and learning path data is stored in your own Supabase database rather than pulled from Khan Academy's API.
Prerequisites
- A Lovable account with at least one project created
- A Supabase database set up in your Lovable project (available via the Cloud tab)
- A list of Khan Academy video URLs you want to feature (collected manually from khanacademy.org)
- Basic understanding of how oEmbed video embedding works
- No API key required — Khan Academy's oEmbed endpoint is public and unauthenticated
Step-by-step guide
Understand what Khan Academy content is publicly accessible
Understand what Khan Academy content is publicly accessible
Before building anything, it is important to understand the current state of Khan Academy's API so you can plan your integration correctly. Khan Academy's public API (api.khanacademy.org) was deprecated in 2018 and provides very limited functionality. The endpoints for exercises, topic trees, and user data require a formal partnership agreement and are not available to independent developers. Attempting to call these endpoints will return 403 Forbidden or empty responses. What IS accessible without authentication: - Khan Academy video URLs on YouTube (all Khan Academy videos are also on YouTube's khanacademy channel) - Khan Academy's own video player pages at khanacademy.org/... which can be embedded via iframe - Khan Academy's oEmbed endpoint at https://www.khanacademy.org/api/labs/shorten/oembed?url={videoUrl} — this returns embed code for any Khan Academy video URL - The public content library browsable at khanacademy.org — you can manually collect URLs The recommended strategy for a Lovable integration is: manually curate the Khan Academy video URLs you want to use, store them in your Supabase database, and use the oEmbed endpoint to get embed code for displaying them. Your Edge Function will handle the oEmbed request (since the endpoint does not support CORS for browser requests). All user progress, bookmarks, and learning path data is stored in your Supabase tables — not fetched from Khan Academy's API. This means setup involves creating the right Supabase schema first, then building UI around it, rather than setting up API credentials.
Create a Supabase table called khan_content with columns: id (uuid), title (text), khan_url (text), subject (text), grade_level (text), description (text), thumbnail_url (text), created_at (timestamptz). Also create a completions table with: id (uuid), user_id (uuid references auth.users), content_id (uuid references khan_content), completed_at (timestamptz). Add RLS policies so users can read all khan_content and can insert/read their own completions.
Paste this in Lovable chat
Pro tip: When collecting Khan Academy URLs, prefer the full URL from the address bar (e.g., https://www.khanacademy.org/math/algebra/x2f8bb11595b61c86:foundation-algebra/x2f8bb11595b61c86:intro-variables/v/what-is-a-variable) rather than shortened URLs, as the full URL contains useful metadata about subject and topic in the path.
Expected result: Your Supabase database has khan_content and completions tables with proper RLS policies. The khan_content table is ready to receive manually curated Khan Academy video URLs.
Create an Edge Function to fetch Khan Academy oEmbed data
Create an Edge Function to fetch Khan Academy oEmbed data
Khan Academy's oEmbed endpoint does not send CORS headers that allow browser requests, so you need an Edge Function to fetch oEmbed data server-side and return it to your frontend. This Edge Function takes a Khan Academy video URL and returns the embed HTML and video metadata. Paste this prompt into Lovable's chat to generate the Edge Function: 'Create a Supabase Edge Function at supabase/functions/khan-oembed/index.ts that accepts a POST request with JSON body { url: "https://www.khanacademy.org/..." }. The function should call https://www.khanacademy.org/api/labs/shorten/oembed?url={encodedUrl}&format=json and return the response. Include CORS headers. If the oEmbed call fails (Khan Academy video not found or URL invalid), return a fallback response that constructs a YouTube embed URL by extracting the video ID from the Khan Academy URL if possible.' Khan Academy videos that exist on YouTube follow a pattern where the YouTube video ID can sometimes be inferred, but the most reliable approach is using Khan Academy's oEmbed endpoint directly. The oEmbed response includes: html (the embed code), title, thumbnail_url, width, height, and author_name. Alternatively, since all Khan Academy videos are also on YouTube, you can bypass the oEmbed approach entirely and embed videos directly using YouTube's iframe embed URL: https://www.youtube.com/embed/{videoId}. The challenge is extracting the YouTube video ID from a Khan Academy URL, which requires either storing both URLs or building a URL conversion function. For simplicity, storing the YouTube URL alongside the Khan Academy URL in your database is the most reliable approach.
Create a Supabase Edge Function at supabase/functions/khan-oembed/index.ts that accepts a POST request with body { url: string }. Call https://www.khanacademy.org/api/labs/shorten/oembed?url={encodeURIComponent(url)}&format=json and return the JSON response with CORS headers. If the fetch fails, return { error: 'Could not fetch oEmbed data', html: null }.
Paste this in Lovable chat
1// supabase/functions/khan-oembed/index.ts2const corsHeaders = {3 'Access-Control-Allow-Origin': '*',4 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',5};67Deno.serve(async (req) => {8 if (req.method === 'OPTIONS') {9 return new Response('ok', { headers: corsHeaders });10 }1112 try {13 const { url } = await req.json();1415 if (!url || !url.includes('khanacademy.org')) {16 return new Response(17 JSON.stringify({ error: 'Invalid Khan Academy URL' }),18 { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }19 );20 }2122 const oEmbedUrl = `https://www.khanacademy.org/api/labs/shorten/oembed?url=${encodeURIComponent(url)}&format=json`;2324 const response = await fetch(oEmbedUrl, {25 headers: { 'User-Agent': 'Mozilla/5.0 (compatible; LovableApp/1.0)' },26 });2728 if (!response.ok) {29 return new Response(30 JSON.stringify({ error: 'oEmbed fetch failed', status: response.status, html: null }),31 { status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }32 );33 }3435 const data = await response.json();3637 return new Response(JSON.stringify(data), {38 headers: { ...corsHeaders, 'Content-Type': 'application/json' },39 });40 } catch (error) {41 return new Response(42 JSON.stringify({ error: error.message, html: null }),43 { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }44 );45 }46});Pro tip: Because Khan Academy's oEmbed endpoint may be slow or occasionally unavailable, consider caching the embed HTML in your khan_content Supabase table (add an embed_html column). Fetch it once when you add a new content item and store it — then serve it from Supabase directly in production rather than calling the oEmbed endpoint on every page load.
Expected result: The Edge Function is deployed and visible in the Cloud tab. When called with a valid Khan Academy video URL, it returns oEmbed data including the embed HTML. The function handles errors gracefully and always returns a JSON response.
Build the video content viewer component
Build the video content viewer component
With the database schema and Edge Function in place, build the React component that displays Khan Academy videos. The component queries your Supabase khan_content table for content, renders video thumbnails in a grid, and shows the embedded player when a user clicks a video. Paste this prompt into Lovable's chat: 'Create a React component called KhanContentViewer that fetches all rows from the khan_content Supabase table filtered by subject (passed as a prop). Display items in a responsive grid of cards showing thumbnail_url, title, subject badge, and grade_level. When a user clicks a card, open a modal showing the embedded Khan Academy video. Get the embed HTML by calling the khan-oembed Edge Function with the item's khan_url. Below the video, show the description and a "Mark as Complete" button. When clicked, insert a row into the completions table. If the user has already completed this item, show a green checkmark instead.' The embed HTML returned by oEmbed includes an iframe tag. In React, you can render it safely using dangerouslySetInnerHTML — but only because this HTML is coming from Khan Academy's own oEmbed endpoint, not from user input. Never use dangerouslySetInnerHTML with user-supplied content. For the iframe size, use a responsive wrapper with a 16:9 aspect ratio: a div with padding-bottom: 56.25% and position: relative, with the iframe inside set to position: absolute and width/height 100%. This ensures the video fills the modal width on all screen sizes. If you stored YouTube URLs alongside Khan Academy URLs in your database (as suggested in Step 2), you can bypass the oEmbed lookup entirely and construct the embed directly: https://www.youtube.com/embed/{youtubeVideoId}?autoplay=1. This is faster and more reliable than calling the oEmbed endpoint.
Create a KhanContentViewer React component that fetches rows from the khan_content Supabase table. Show items in a grid of cards with thumbnail, title, subject, and grade level. Clicking a card opens a modal. In the modal, call the khan-oembed Edge Function with the item's khan_url to get embed HTML, display it in a responsive 16:9 iframe container, show the description, and add a Mark as Complete button that inserts to the completions table. Show a completed badge if the user already has a completion record for this item.
Paste this in Lovable chat
Pro tip: Add a seed script or use the Supabase Table Editor to add 5-10 Khan Academy video URLs to your khan_content table manually before testing. This gives you real content to display and lets you validate the full flow before presenting to users or stakeholders.
Expected result: A content viewer appears in your app showing Khan Academy video cards from your Supabase database. Clicking a card opens a modal with an embedded Khan Academy video player. The Mark as Complete button works and shows a checkmark on already-completed items.
Add progress tracking and learning path management
Add progress tracking and learning path management
To make the integration genuinely useful for educational apps, add a progress dashboard that shows each user's learning progress and a way to organize content into structured learning paths. First, add a learning_paths table to your Supabase database and a learning_path_items junction table: 'Create two new Supabase tables: learning_paths (id uuid, title text, description text, created_by uuid references auth.users, is_public boolean, created_at timestamptz) and learning_path_items (id uuid, path_id uuid references learning_paths, content_id uuid references khan_content, order_index integer). Add RLS policies so all users can read public learning paths and their items. Owners can insert/update/delete their own paths.' Then build a progress dashboard component that shows: total videos completed, completion percentage per subject, a streak counter based on consecutive days with completions, and a recommended next video (the next incomplete item in a learning path the user is following). For the recommendations, a simple SQL query in your Edge Function works well: select the next learning_path_item where the content_id does not appear in the user's completions table, ordered by order_index. This gives you a basic "next lesson" recommendation without any machine learning. For complex multi-step learning path designs or when you need to integrate Khan Academy content into a larger curriculum management system, RapidDev's team can help architect the data model and query logic for your specific use case.
Add a progress dashboard page showing: total Khan Academy videos completed, a breakdown by subject (math, science, history etc.), the user's learning streak in days, and a 'Continue Learning' card showing the next incomplete video in their current learning path. Fetch completion data from the Supabase completions table joined with khan_content. Calculate the streak by checking consecutive days with at least one completion in the last 30 days.
Paste this in Lovable chat
Pro tip: For subject categories, use a consistent set of values when inserting into khan_content (e.g., 'Math', 'Science', 'History', 'Computing'). Inconsistent capitalization or naming will break the subject-based filtering and progress charts.
Expected result: A progress dashboard shows each user's completion statistics, subject breakdown, and learning streak. The Continue Learning card surfaces the next video in their current learning path. All data comes from your Supabase tables, not from Khan Academy's API.
Common use cases
Curated learning path viewer for a specific subject
Build a structured learning path where students follow a teacher-curated sequence of Khan Academy videos and exercises. Progress is tracked in Supabase, and students can see which lessons they have completed and which are next.
Create a learning path viewer that displays a curated list of Khan Academy videos stored in a Supabase table called learning_path_items (with fields: title, khan_video_url, description, order_index, subject). Show each item as a card with title, description, and an embedded Khan Academy video player using the oEmbed URL. When a student marks a video as watched, update a completions table in Supabase with user_id, item_id, and completed_at. Show a progress bar based on completion percentage.
Copy this prompt to try it in Lovable
Subject-specific homework helper with embedded videos
Build a homework support app where students can browse Khan Academy videos by subject area, bookmark videos for later, and track which topics they have studied. Teachers can see aggregate data on which topics students are watching most.
Build a homework helper app with a subject browser that shows math, science, and history topics. Each topic links to a curated list of Khan Academy videos stored in Supabase. Students can click a video to watch it embedded on the page, add it to their bookmarks, and mark it as helpful. Show a teacher dashboard with the most-watched videos this week and which students are most active.
Copy this prompt to try it in Lovable
Supplementary resources section in an LMS
Add a Khan Academy video library section to an existing Lovable learning management app, letting instructors attach relevant Khan Academy videos to their lessons as supplementary material.
Add a supplementary resources section to each lesson in my app. Instructors should be able to paste a Khan Academy video URL and a description, and it will be saved to a lesson_resources table. Students viewing a lesson see these resources in a sidebar. When they click a resource, embed the Khan Academy video in a modal using the oEmbed endpoint to get the embed code.
Copy this prompt to try it in Lovable
Troubleshooting
oEmbed Edge Function returns error or empty HTML for some Khan Academy URLs
Cause: Khan Academy's oEmbed endpoint does not support all content types — it works for video content (paths with /v/ in the URL) but may return errors for exercise pages, article pages, or content that has been moved or removed.
Solution: Limit your khan_content table to video URLs (those containing /v/ in the path). For exercise and article content, store the direct Khan Academy URL and open it in a new tab rather than embedding it. Add URL validation in your Edge Function to reject non-video URLs before attempting oEmbed. As a fallback, store the YouTube URL alongside the Khan Academy URL — if oEmbed fails, construct a YouTube embed directly.
Embedded videos show correctly in development but are blocked in the deployed app
Cause: Khan Academy and YouTube iframes can be blocked by browser Content Security Policy (CSP) headers if your app's CSP does not include khanacademy.org and youtube.com in the frame-src directive.
Solution: Ask Lovable to add Content Security Policy headers to your app that allow iframes from khanacademy.org and youtube.com: 'Add a Content Security Policy to allow iframe embeds from khanacademy.org and www.youtube.com in the frame-src directive.' Alternatively, if you use a Supabase Edge Function to serve the page, add the CSP header there. On most Lovable deployments, this is set in the Vercel configuration or via a meta tag.
Progress data is not appearing after a student marks a video as complete
Cause: The insert to the completions table is failing silently due to a missing RLS policy that allows authenticated users to insert their own completion records.
Solution: Open the Lovable Cloud tab → Database → Tables → completions. Check the RLS policies. There should be a policy that allows INSERT when auth.uid() = user_id. If missing, prompt Lovable: 'Add an RLS policy to the completions table that allows authenticated users to insert rows where user_id equals their own auth.uid(). Also add a policy allowing users to read their own completions.' After adding the policy, test the Mark as Complete button again.
Best practices
- Store embed HTML in your Supabase khan_content table after the first oEmbed fetch rather than calling the oEmbed endpoint on every page load — Khan Academy's oEmbed endpoint has no SLA and can be slow
- Use YouTube embed URLs as a fallback when Khan Academy's oEmbed endpoint fails — all Khan Academy videos exist on the khanacademy YouTube channel
- Keep your khan_content table manually curated and well-organized with consistent subject and grade_level values — this enables filtering and subject-based progress tracking
- Track all user progress in your own Supabase database rather than relying on Khan Academy's user progress API, which requires a formal partnership and is not accessible to independent developers
- Add an is_active boolean column to your khan_content table so you can soft-delete content that has moved or been removed from Khan Academy without losing historical completion data
- Validate Khan Academy URLs before inserting them into your database — check that the URL contains khanacademy.org and ideally /v/ for video content
- Use consistent grade level values (e.g., 'K-2', '3-5', '6-8', '9-12', 'College') to enable meaningful filtering and curriculum alignment features
Alternatives
Choose Coursera if you need a partner API with structured course catalog data, university-accredited content, and programmatic enrollment tracking for corporate or institutional learning.
Choose Google Classroom if you need real classroom management features — assignment creation, grade tracking, and student rosters — rather than just embedding educational video content.
Choose Moodle if you need a fully featured open-source LMS with a proper API for courses, grades, and users, rather than a curated video embedding approach.
Frequently asked questions
Is Khan Academy's API still available in 2026?
Khan Academy's public API is largely deprecated. The full API endpoints for exercises, topic trees, and user data require a formal partnership agreement and are not available to independent developers. The oEmbed endpoint for embedding videos remains accessible. For most Lovable integration use cases, the recommended approach is embedding videos via oEmbed and tracking progress in your own Supabase database.
Do I need an API key to embed Khan Academy videos?
No. Khan Academy's oEmbed endpoint is public and does not require authentication. You pass the video URL as a query parameter and receive embed HTML in return. The only reason to use an Edge Function for this is CORS — oEmbed responses from Khan Academy cannot be fetched directly from browser JavaScript due to missing CORS headers.
Can I track whether students have actually watched a video, not just clicked on it?
Not through Khan Academy's API — that level of tracking requires integration with Khan Academy's user data, which is not publicly accessible. What you can track is whether the student clicked the Mark as Complete button in your Lovable app. For more granular video engagement tracking, consider using YouTube's embedded player API (which provides play, pause, and completion events via JavaScript) and storing that data in your Supabase completions table.
Can I use Khan Academy content commercially in my app?
Khan Academy's content is licensed under Creative Commons Attribution-NonCommercial-ShareAlike. You can embed and link to their videos freely, but you cannot rehost the video files, remove attribution, or use the content in a for-profit context without their permission. If you are building a commercial educational product, review Khan Academy's content licensing terms and consider reaching out to them about a formal partnership.
What is the best alternative if I need a full educational API with course data and user progress?
If you need a real REST API with course catalogs, user progress data, and enrollment management, look at platforms like Coursera (partner API), Thinkific (API key auth), or Moodle (web services API). These platforms provide structured programmatic access to course data and are designed for integration. Khan Academy is better suited for content embedding rather than full API integration.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation