<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: l don</title>
    <description>The latest articles on DEV Community by l don (@l_don_05aabc782c2f3ded233).</description>
    <link>https://dev.to/l_don_05aabc782c2f3ded233</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4004223%2Fc10e3a85-d0b6-437d-bc35-efd5dd4431e7.png</url>
      <title>DEV Community: l don</title>
      <link>https://dev.to/l_don_05aabc782c2f3ded233</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/l_don_05aabc782c2f3ded233"/>
    <language>en</language>
    <item>
      <title>api tutorial webdev showdev python opensource</title>
      <dc:creator>l don</dc:creator>
      <pubDate>Fri, 26 Jun 2026 15:58:40 +0000</pubDate>
      <link>https://dev.to/l_don_05aabc782c2f3ded233/api-tutorial-webdev-showdev-python-opensource-2i60</link>
      <guid>https://dev.to/l_don_05aabc782c2f3ded233/api-tutorial-webdev-showdev-python-opensource-2i60</guid>
      <description>&lt;h1&gt;
  
  
  I Built a Multi-Platform Video Downloader API in 2 Days
&lt;/h1&gt;

&lt;p&gt;If you've ever needed to programmatically download videos from social media — for content repurposing, analytics, or automation — you know the pain. Every platform has its own quirks, most existing APIs only support one platform, and the good ones are expensive.&lt;/p&gt;

&lt;p&gt;So I built my own. Here's what I learned.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;I needed to extract video URLs from multiple platforms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;YouTube Shorts (no login needed)&lt;/li&gt;
&lt;li&gt;TikTok / Douyin&lt;/li&gt;
&lt;li&gt;Instagram Reels&lt;/li&gt;
&lt;li&gt;Bilibili&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What I found on the market:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Single-platform APIs&lt;/strong&gt;: great for one use case, useless if you need more&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expensive all-in-one tools&lt;/strong&gt;: $50-100/month for basic access&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open-source tools like yt-dlp&lt;/strong&gt;: powerful but not API-friendly&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;p&gt;A single API endpoint that handles 10+ platforms. Built with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FastAPI&lt;/strong&gt; — async Python, auto-generated docs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;yt-dlp&lt;/strong&gt; — battle-tested extraction engine&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker + Render&lt;/strong&gt; — $0 hosting for the first 50k requests
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Core extraction — dead simple
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_extract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;yt_dlp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;YoutubeDL&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;quiet&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;format&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;best&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ydl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ydl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extract_info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;download&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;thumbnail&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;thumbnail&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="c1"&gt;# ...more metadata
&lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  API Usage
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://video-downloader-api-eyqj.onrender.com/extract &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"url":"https://www.youtube.com/shorts/dQw4w9WgXcQ"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Rick Astley - Never Gonna Give You Up"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://manifest.googlevideo.com/..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"duration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;213&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"view_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1786552159&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What Works (and What Doesn't)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;YouTube&lt;/td&gt;
&lt;td&gt;Great&lt;/td&gt;
&lt;td&gt;Shorts + regular, no auth&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Instagram&lt;/td&gt;
&lt;td&gt;Works&lt;/td&gt;
&lt;td&gt;Needs cookies for some content&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TikTok&lt;/td&gt;
&lt;td&gt;Tricky&lt;/td&gt;
&lt;td&gt;Server IPs get blocked, exploring proxy rotation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bilibili&lt;/td&gt;
&lt;td&gt;Works&lt;/td&gt;
&lt;td&gt;Some anti-bot measures&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Douyin&lt;/td&gt;
&lt;td&gt;Works&lt;/td&gt;
&lt;td&gt;Requires browser cookies&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. yt-dlp is a beast.&lt;/strong&gt; It handles 1800+ sites. Wrapping it in FastAPI took 30 lines of code. The real work was error handling — each platform fails differently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Geo-restrictions are the silent killer.&lt;/strong&gt; TikTok blocked my Render server IP immediately. If you're building a public API, budget for proxy infrastructure from day one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Cookie support is essential.&lt;/strong&gt; Chinese platforms (Douyin, Xiaohongshu) require fresh browser cookies. I added a &lt;code&gt;X-Cookie&lt;/code&gt; header that accepts Netscape-format cookies exported from the browser.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Free hosting is possible for MVPs.&lt;/strong&gt; Render's free tier + Docker auto-deploy means I pay $0 while validating the idea.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Proxy rotation for TikTok support&lt;/li&gt;
&lt;li&gt;Webhook support (notify when video is ready)&lt;/li&gt;
&lt;li&gt;Direct S3 upload (store the extracted video)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;The API is available on RapidAPI with a free tier (50 requests/month):&lt;/p&gt;

&lt;p&gt;[&lt;a href="https://rapidapi.com/ldspn115/api/multi-platform-video-downloader" rel="noopener noreferrer"&gt;https://rapidapi.com/ldspn115/api/multi-platform-video-downloader&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;Source code on GitHub: [&lt;a href="https://github.com/ldspn115-ctrl/video-downloader-api" rel="noopener noreferrer"&gt;https://github.com/ldspn115-ctrl/video-downloader-api&lt;/a&gt;]&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built this in a weekend. Feedback and feature requests welcome in the comments!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Tags: &lt;code&gt;#api&lt;/code&gt; &lt;code&gt;#tutorial&lt;/code&gt; &lt;code&gt;#webdev&lt;/code&gt; &lt;code&gt;#showdev&lt;/code&gt; &lt;code&gt;#python&lt;/code&gt; &lt;code&gt;#opensource&lt;/code&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>python</category>
      <category>showdev</category>
      <category>webscraping</category>
    </item>
  </channel>
</rss>
