動画の直リンクをダウンロードできない場合

403、404、CORS、空ファイル、非対応形式、レジューム不可など、MP4・WebMの直リンクダウンロード問題をcurl診断コード付きで解説します。

動画の直リンクとは「1つのURL=1つのファイル」で取れるダウンロードのこと。MP4、WebM、MOV、MKVならクリックで再生でき、URLさえ手に入れれば保存できます。M3U8やMPDのようにセグメントを集めて結合するストリームとはまったく別物です。この記事では直リンクダウンロードでありがちな落とし穴を順に潰していき、curlコマンド付きで「どこで詰まっているか」を特定できるようにします。

まず整理:直リンクとストリーミングは別物

直リンクの失敗原因は、半分以上がストリーミングの考え方を直リンクに持ち込んでいることです。まずこの2つを分けましょう:

直接ファイルHLS / DASH ストリーム
構造単一ファイルマニフェスト + 数百のセグメント
ダウンロード1リクエストで完了セグメントを集めて結合
失敗の特徴全体が失敗(403/404/空ファイル)一部セグメント失敗、結合後に乱れや無音
調べる場所リクエストヘッダー、URLの有効性、形式マニフェスト、セグメント、鍵、結合

つまり以下の症状は基本的に直リンク専用です。動画が実はHLSやDASHストリームなら、対応記事へどうぞ:M3U8(HLS)ダウンロード失敗 または DASHで音が出ない。直リンクの検出・対応形式の範囲は 動画検知 を参照してください。

まず試すこと

先にこの手順を一通り試せば、8割は解決します:

  1. 動画が実際に再生されるページを開き、数秒再生して動画が本当に読み込まれるのを確認します。
  2. FlowPick拡張機能を開き、リソース一覧から動画ファイルを選びます。サムネイルや表紙は選ばないこと。
  3. 右側のプレビューが正常に再生されるのを確認し、形式が間違いなければダウンロードします。

それでもダメなら、下の症状に当てはめてください。拡張機能でのファイル選択や保存先の指定方法は 使い方 — 単一リソースのダウンロード を参照してください。

症状1:403 Forbidden

症状:ダウンロードが即失敗する。またはブラウザでURLを直接開いても403になる。

直リンク動画で本当に「権限がない」ケースは稀で、ほとんどはリクエストヘッダーが間違っているだけです。配信元がよく行うチェックはこちら:

  • Refererチェック:特定ページからのリクエストを要求。空のRefererや知らない参照元は即拒否。
  • Cookie / ログイン状態:ログインCookieが無い、またはセッションが切れている。
  • 一時トークン:URLに ?token=xxx&expires=yyy が付き、期限切れで403。
  • 地域 / IP制限:CDNが出口IPで配信可否を決める。

直リンクのURLを拾ってcurlで再現してみます(URLは自分のものに置き換えてください):

# ヘッダーなしの素のリクエスト。何が返るか確認
curl -s -o /dev/null -w "素のリクエスト: %{http_code}\n" "https://cdn.example.com/videos/lesson1.mp4"

# ページのRefererを付けて再試行
curl -s -o /dev/null -w "Referer付き: %{http_code}\n" \
  -H "Referer: https://www.example.com/course/123" \
  "https://cdn.example.com/videos/lesson1.mp4"

Refererを付けると通るなら、それはホットリンク対策です。ブラウザ拡張機能で解決します:拡張機能は元ページのコンテキストで動くため、RefererとCookieが自動で付きます。v1.1.1以降はホットリンク対策プロキシも内蔵され、プレビューもダウンロードも自動でリクエストヘッダーを補完してレスポンスを検証するので、HTMLのエラーページを動画として保存する事故も防げます。オンラインツールにはこの力はありません——自分のドメインで動くため、対象サイトのCookieを付与できないのです。アップグレード方法は インストール — 拡張機能の更新、ホットリンク対策プロキシの詳細は FlowPick v1.1.1 アップデート を参照してください。

症状2:404 URL期限切れ、またはファイル削除

症状:以前はダウンロードできたのに今日は404。または誰かからもらった直リンクが取れない。

よくあるのは次の3つ:

  • 署名付きURLの期限切れ:多くのクラウドストレージ(Alibaba Cloud OSS、Tencent Cloud COSなど)の直リンクは有効期限付きで、数分から数時間で失効します。
  • ファイルの削除:アップロード者が消した、またはCDNキャッシュがクリアされた。
  • 間違ったURL:コピーしたのが視聴ページのURLで、ファイルの直リンクではない。

URL自体が生きているか確認します:

curl -sI "https://cdn.example.com/videos/lesson1.mp4" | head -n 8

ステータスコードと Content-Type を見てください。Content-Typetext/html なら、そのURLは動画ではなくWebページを指しています。URLが本当に失効しているならどうしようもありません——元の動画ページに戻って再検出し、新しい直リンクを取り直してください。

症状3:CORS クロスオリジン遮断

症状:オンラインツールがCORSエラーを出す。またはダウンロードしたファイルが壊れている。

これはオンラインツール特有の問題です。オンラインツールは flowpick.com の自ドメインで動くため、ブラウザの同一オリジンポリシーがクロスオリジン読み取りを遮断します。拡張機能は違います。拡張権限で動くため同一オリジンポリシーに縛られず、検出範囲も広い。両者の違いは オンラインツール — 拡張機能との違い を参照してください。

解決策は一言:直リンクはオンラインツールではなく拡張機能で取る。拡張機能は動画の元ページの中で動くので、Referer・Cookie・クロスオリジンの問題が一気に解決します。

症状4:空ファイル、または再生できない

症状:ダウンロードは「成功」するのにファイルが数KBしかない。またはプレイヤーで開けない。

十中八九選ぶ対象を間違えています:動画ファイルではなく、HTMLページ、サムネイル、表紙画像、プレビューAPIのレスポンスを選んでいます。こうしたレスポンスはサイズが小さく、Content-Typetext/htmlimage/* です。

curlでこのURLが実際に何を返すか確認します:

curl -sI "https://cdn.example.com/cover/lesson1.jpg"
# Content-Type と Content-Length を見る

text/html を指しているなら、それはただのWebページです。拡張機能に戻り、リソース一覧から video/mp4video/webm といった video/* タイプの項目を選び、右側のプレビューで再生できることを確認してからダウンロードしてください。ファイル名が文字化けしていたり拡張子が無い場合は、ダウンロード後に手動で .mp4 を付けて試してください。

症状5:一時停止・途中再開ができない

症状:ダウンロードは開始できるが、一時停止して再開すると最初からやり直し。または一時停止ボタン自体が無い。

これはサーバーが HTTP Range に対応しているかどうかで決まります。Rangeを使うとクライアントはファイルの一部だけをリクエストでき、一時停止・再開はこれに依存します。サーバーがRangeを有効にしていなければ、ブラウザはファイル全体をダウンロードするしかなく、途中再開は不可能です。

サーバーが対応しているか確認します:

curl -s -o /dev/null -w "Rangeリクエスト: %{http_code}\n" \
  -H "Range: bytes=0-1023" \
  "https://cdn.example.com/videos/lesson1.mp4"
# 206 = Range対応、途中再開可能
# 200 = 全ファイルが返却、Range非対応

206 なら対応、200(全ファイル)なら非対応です。非対応でもダウンロード自体はできます。ただ途中再開はできないので、回線が不安定なときは一気に終わらせるのがおすすめです。これはサーバー側の能力の問題で、ツールの問題ではありません。

症状6:形式またはコーデック非対応

症状:ファイルはダウンロードできてサイズも正常なのに、プレイヤーが「非対応の形式」と出る、または黒画面になる。

まずコンテナコーデックを分けて考えます:.mp4 はコンテナで、中身はH.264かもしれないし、H.265/HEVCやAV1かもしれません。コンテナ対応=コーデック対応ではありません。プレイヤーは中のコーデックをデコードできて初めて再生できます。よくある罠:

状況症状対処
MP4の中身がH.265/HEVC古いプレイヤーで黒画面H.264に変換するかプレイヤーを変える
WebMの中身がAV1ハードウェアデコード非対応H.264/VP9に変換
高画質の直リンクが大容量ブラウザのメモリ逼迫次の節へ

直リンクの検出・ダウンロード時にFlowPickはコーデック情報を読み出します。本当にコーデックが原因なら、フォーマット変換 — 出力フォーマット選択ガイド で互換性の高いH.264 MP4に変換してください。プレイヤーが何に対応しているかは ブラウザ互換性 を参考にしてください。

症状7:大容量ファイル、またはブラウザが固まる

症状:数百MBの直リンクをダウンロード途中でページが固まる。またはダウンロード後にブラウザが明らかに重くなる。

ブラウザでファイルを保存するにはメモリを通ります。FlowPickは優先的に File System Access API(ディレクトリを選んでストリーム書き込み、メモリを使わない)を使い、非対応時はStreamSaverやBlobにフォールバックします。特にBlobモードはファイル全体を先にメモリへ読み込むため、大容量だと固まりがちです。Blobモードの具体的なハード制限は 既知の制限 — Blob モードハード制限、対応する既知バグは 既知の制限 — 大容量ファイル Blob ダウンロードでフリーズする可能性あり を参照してください。

対処:

  • 「保存ディレクトリを選択」を優先 — File System Access APIが発動し、大容量でもストリーム書き込みできます。
  • そのボタンが無いブラウザ(またはモバイル)なら、動画を低画質に切り替えてからダウンロード。
  • 本当に大容量なら、その1つだけをダウンロードし、同時に複数走らせない。

診断ツール早見表

F12 で開発者ツールを開き、この表で素早く切り分けます:

確認したいことパネル手順
直リンクリクエストの戻り値Networkmp4 / webm で絞り込み、Status列を見る
動画が返ってきたかNetworkレスポンスの Content-Typevideo/* か確認
Referer/Cookieが付いたかNetwork → リクエスト → HeadersRequest Headersを確認
CDNに帯域制限されていないかNetwork1リクエストの所要時間と速度を見る

ブラウザ環境の問題が疑わしいなら、Consoleでこれを実行して環境レポートを作り、フィードバックの際に貼り付けてください:

const report = {
  ua: navigator.userAgent,
  fsa: 'showDirectoryPicker' in window,
  sab: typeof SharedArrayBuffer !== 'undefined',
  coi: self.crossOriginIsolated,
  storage: await navigator.storage?.estimate().catch(() => null),
  ts: new Date().toISOString(),
}
console.log(JSON.stringify(report, null, 2))

レポートにはブラウザの環境情報のみが含まれ、閲覧履歴や個人データは一切入りません。

本当にダウンロードできない場合

  • DRM保護:Widevine / PlayReady / FairPlayで暗号化されたコンテンツ。FlowPickは明確に非対応で、クラックもしません。
  • ログイン・ペイウォール:ログインや購入をしないと直リンクのURL自体が手に入らないコンテンツ。
  • APIの私有化:動画データが独自プロトコルやアプリ内署名を通るもので、通常の直リンクを発行しない。
  • URLの恒久失効:配信元がファイルを削除済み。

これらは設計上の非対応であり、バグではありません。当たったら発想を変えて:画面収録するか、コンテンツ提供者に許諾を求めましょう。より完全な境界リストは 既知の制限 を参照してください。

関連ドキュメント