うちのYouTubeの短い動画を、Threadsにも自動で流せるようにしました。最初の本番投稿は、1回で通りました。ただ、そこまでに2つの壁がありました。Xの自動投稿はお金がかかることと、ThreadsはYouTubeのURLでは動画を投稿できないことです。
先に結論です。2026年9月時点で、無料で自動投稿できるのはThreadsのほうでした。ThreadsのAPIで動画を投稿するには、動画のファイルそのものがネット上の住所に置いてある必要があります。うちでは、自分のブログのサーバーに動画を一時的に上げて、投稿が終わったら消す形にしました。この記事では、その手順と、実際の実行結果を置いておきます。

Xは有料、Threadsは無料だった
最初は、XとThreadsの両方に自動で投稿するつもりでした。調べてみると、状況はこうでした(2026年9月時点・うちの調べ)。
| X | Threads | |
|---|---|---|
| 自動投稿(API) | 無料枠なし。1投稿あたり約2円、リンク付きは約30円の従量課金 | 無料 |
| Xの有料プラン | 入ってもAPIは使えない(別の契約) | ― |
| アカウント | 単体で作れる | 日本ではInstagramのアカウントが必要 |
| 動画の投稿 | ― | できる。ただし動画ファイルの公開URLが必要 |
毎日投稿すると、Xはリンク付きで月900円ほどになります。まだ見てくれる人が少ない段階なので、Xは手で投稿、Threadsは自動と決めました。
ThreadsのAPIを使えるようにするまで
ThreadsのAPIは、Metaの開発者サイトで「アプリ」を作って使います。流れはこうです。
- Instagramのアカウントを作り、そのアカウントでThreadsを始める
- Metaの開発者サイトに、Facebookでログインして開発者登録をする
- アプリを作り、用途で「ThreadsのAPIを使う」を選ぶ
- 権限を付ける(基本の読み取り・投稿・分析。あとで消すための削除の権限もあると便利)
- 投稿したいThreadsのアカウントを、アプリのテスターに招待する
- Threadsの設定の「ウェブサイトのアクセス許可」で、その招待を承認する
- 開発者サイトでアクセストークンを作り、自分のパソコンに保存する
つまずいた所が2つありました。
- アプリ一覧を開くと、トップページに戻される。Facebookにログインしていないのが原因でした。先にログインしてから開発者登録に進みます
- リダイレクト先のURLの欄が保存できない。URLを打ったあと、Enterキーで確定しないと入力したことになりません。見た目は入っているのに、保存を押すと「URLを指定してください」と言われます
トークンは60日で切れます。延長のAPIがあるので、うちでは週に1回延長しています。トークンは合言葉と同じなので、チャットや記事に貼らず、ファイルにだけ置いておきます。
YouTubeのURLでは、動画を投稿できない
いちばんの壁はここでした。ThreadsのAPIで動画を投稿するときは、動画ファイルが置いてある住所を渡します。Threads側がその住所から動画を取りに来るしくみです。
最初は、もうYouTubeに上げてあるのだから、そのURLを渡せばいいと考えました。でも、YouTubeのURLは動画を見るためのページの住所で、動画ファイルそのものの住所ではありません。Threadsがそこへ取りに行っても、動画は受け取れません。
そこで、動画の置き場所に自分のブログのサーバーを使うことにしました。WordPressのメディアに動画を一時的に上げれば、ネット上に動画ファイルの住所ができます。投稿が終わったら消します。
実際の投稿:ブログに上げて、渡して、消す
この流れを1本の道具にまとめて、最初の本番投稿をしました。その実行結果です(本文と住所の一部は省略しています)。

APIの呼び出しは3段です。①動画の住所と本文を渡して「入れ物」を作る。②Threads側が動画を取り込み終わるのを待つ。③入れ物を公開する。動画は取り込みに時間がかかるので、②を飛ばすと失敗します。
import json, time, urllib.request, urllib.parse
API = "https://graph.threads.net/v1.0"
def call(method, url, params):
data = urllib.parse.urlencode(params).encode() if method == "POST" else None
if method == "GET":
url += "?" + urllib.parse.urlencode(params)
return json.load(urllib.request.urlopen(urllib.request.Request(url, data=data, method=method)))
def post_video(token, text, video_url):
# 1. 入れ物を作る(動画ファイルの公開URLを渡す)
c = call("POST", API + "/me/threads",
{"media_type": "VIDEO", "text": text, "video_url": video_url, "access_token": token})
# 2. 取り込みが終わるまで待つ
while True:
st = call("GET", API + "/" + c["id"], {"fields": "status,error_message", "access_token": token})
if st["status"] == "FINISHED": break
if st["status"] == "ERROR": raise RuntimeError(st)
time.sleep(5)
# 3. 公開する
return call("POST", API + "/me/threads_publish", {"creation_id": c["id"], "access_token": token})
落とし穴:消したのに、外からは見えていた
本番の前に、ブログへの一時アップと削除だけを試しました。WordPressの上では、動画はちゃんと消えていました。ところが、外からその住所を開くと、まだ動画が返ってきました。
原因は、サーバーのキャッシュ(一度配ったファイルの写しを、しばらく手元に置いておくしくみ)でした。消したのは元のファイルで、写しはしばらく残ります。キャッシュを通さずに開くと、ちゃんと「見つかりません」になりました。本番で使った動画は、投稿から半日ほどたって確かめると、外からも消えていました。

うちの場合、流すのはもう公開している動画なので、写しがしばらく残っても困りません。でも、人に見せたくないファイルを一時置き場に使うのはやめたほうがいいです。「消した」と「外から見えない」は、同じではありません。

まとめ
- 2026年9月時点で、無料で自動投稿できるのはThreads。Xは従量課金で、有料プランに入ってもAPIは使えない
- ThreadsのAPIは、日本ではInstagramのアカウントが前提。テスターに招待し、Threads側で承認してからトークンを作る
- リダイレクト先のURLは、Enterで確定しないと保存できない
- 動画は動画ファイルの公開URLが要る。YouTubeのURLはページの住所なので使えない
- 自分のブログに一時的に上げて、投稿後に消すと置き場に困らない。ただしキャッシュに写しが残るので、見せたくないファイルには使わない
AIに任せられる自動化のアイデアは個人でできるAI自動化アイデア10選にまとめています。Threadsでは、うちのYouTubeの短い動画を流しています。

