楽天APIが2026年に大改変。エラーメッセージが嘘をついていた
ブログの商品カードを自動化しようとしたら、3連続で門前払いされた
こんにちは、へっぽこITエンジニアのやまさんです。
このブログ、記事の中でときどき「使った道具」を紹介しています。あれを毎回手作業でリンク化するのが地味にしんどい。商品名・価格・画像・アフィリエイトリンクを一気に取ってきて、商品カードを自動生成できたらどんなに楽か……ということで、楽天商品検索APIを叩くスクリプトを書き始めました。
「まあ、公開APIだし30分もあれば動くでしょ」と思っていました。甘かったです。
結果として、動き始めるまでに3段階でつまずきました。しかも最後の3つ目は、エラーメッセージが指している名前と、実際に検証されているものが食い違っているという、なかなか意地の悪いやつでした。ネットで見つかる解説記事はどれも以前の仕様のままで、答えが書いてある場所がどこにもありません。
この記事を読み終わるころには、2026年時点の楽天商品検索APIを叩くための「新しいエンドポイント・accessKey・Origin ヘッダー」の3点セットが揃って、コピペで動く最小コードが手に入ります。同じ403で消耗している人の時間を、まるっと節約できたら嬉しいです。
先に結論だけ言っておきます。
403 の
HTTP_REFERRER_MISSINGは、Refererを送っても直りません。必要なのはOriginヘッダーです。
今回使ったもの
道具というほど大げさなものは使っていません。むしろ「情報」が今回の主役でした。
- 楽天ウェブサービス(楽天商品検索API) … 商品名・価格・画像URL・アフィリエイトリンクをまとめて取得できる公式API。無料で使えます。アプリIDや accessKey は Rakuten Developers の管理画面から発行します
- Python + requests … 今回のような「ヘッダーを1つずつ変えて総当たりする」作業に、これ以上向いた組み合わせはありません
- 自分のブログのドメイン … 後述しますが、これがないと話が始まりません。API側の「許可されたウェブサイト」に登録したドメインが、そのまま認証の材料になります
有料のものは1つもありません。かかったのは、半日ぶんの気力だけです。
動くまでに3段階でつまずいた
つまずき1: 新しいアプリIDが、昔のエンドポイントに弾かれる
まずは素直に、ネットでよく見かけるエンドポイントに投げてみます。新規に発行したアプリIDは、UUID形式(df10456b-bb97-... みたいなやつ)でした。
GET https://app.rakuten.co.jp/services/api/IchibaItem/Search/20220601
?applicationId=df10456b-bb97-...返ってきたのがこれ。
400 {"error_description":"specify valid applicationId","error":"wrong_parameter"}「有効なアプリIDを指定してください」。 いやいや、たった今コピペしてきたばかりなんですが……。
ここで15分くらい、管理画面とターミナルを行ったり来たりしました。スペースが混じってないか、改行が入ってないか。全部シロ。
正解は、アプリIDではなくエンドポイントのほうが変わっていた、でした。
新: https://openapi.rakuten.co.jp/ichibams/api/IchibaItem/Search/20260701ドメインからして別物(app.rakuten.co.jp → openapi.rakuten.co.jp)です。新しく発行したアプリIDは新エンドポイント向けのもので、それを旧エンドポイントに投げていたから「そんなIDは知らない」と言われていた、というわけです。
エラーメッセージが「applicationIdが不正」と言っているので、犯人はIDだと思い込んでしまう。この記事、最初から最後までこの構図です。
つまずき2: accessKey という新顔が要求される
エンドポイントを新しいものに差し替えて、再挑戦。
400 {"errors":{"errorCode":400,
"errorMessage":"accessKey must be present as a query parameter or in the header"}}今度は素直なメッセージです。applicationId に加えて accessKey が必要になっていました。pk_ で始まる文字列で、Rakuten Developers の「あなたのアプリ」の画面から取得できます。
これはメッセージのとおりに追加すれば通るので、実質ノーダメージ。むしろ「ちゃんと理由を教えてくれるエラー、ありがたいな」と思ったのを覚えています。このあと、その優しさが恋しくなります。
本題。犯人は Referer ではなく Origin だった
accessKey を付けて、いよいよ通るはず。そう思って実行した結果がこれです。
403 {"errors":{"errorCode":403,
"errorMessage":"REQUEST_CONTEXT_BODY_HTTP_REFERRER_MISSING"}}HTTP_REFERRER_MISSING。「リファラが無いよ」と、これ以上ないくらいはっきり書いてあります。じゃあ送りましょう。
headers = {"accessKey": KEY, "Referer": "https://yamasun-diy.com/"}→ 403 REQUEST_CONTEXT_BODY_HTTP_REFERRER_MISSING変わりません。
ここからが長かった。末尾のスラッシュを外す、http にしてみる、大文字小文字を変える。全部403。ヘッダーじゃなくてクエリパラメータなのかもしれないと思い、httpReferrer・httpReferer・requestContextBody と、思いつく名前を片っ端から試しました。
全部403。 メッセージの文字列すら1文字も変わりません。
正直このあたりで「アプリの登録内容がそもそも間違っているのでは」と疑い始めていました。でもその前に、もう1つだけ候補が残っていたんです。「どこから来たか」を伝えるヘッダーは、Referer だけじゃない。
headers = {"accessKey": KEY, "Origin": "https://yamasun-diy.com"}→ 200 OK ✅通りました。
念のため、ヘッダーの組み合わせを変えて切り分けた結果がこちらです。
| 送ったヘッダー | 結果 |
|---|---|
Referer のみ | ❌ 403 ..._HTTP_REFERRER_MISSING |
Origin のみ | ✅ 200 |
| 両方 | ✅ 200 |

はっきりしました。Referer は、あってもなくても結果に一切影響しません。 検証されているのは Origin ただ1つです。にもかかわらず、エラーメッセージは HTTP_REFERRER_MISSING と名乗る。
Referer と Origin は、どちらも「このリクエストはどこから来たか」を伝えるヘッダーという意味では親戚です。ざっくり言えば、Referer が「このページから飛んできました」とURLまるごと伝えるのに対し、Origin は「このサイトから来ました」とドメインだけを伝える、ブラウザのCORS(別ドメインへのアクセス制御)で使われるほうの子。似ているけれど別物で、今回検証されていたのは後者だけでした。
新しいAPIがブラウザからの利用を前提に設計されると、こういうズレが生まれやすいのだと思います。そして、「Refererを送っても403が直らない」という報告がネット上に複数転がっているのは、おそらく全員がこのエラーメッセージに素直に誘導されているからでしょう。私もその一人でした。
コピペで動く最小コード
ここまでの3点セットを全部入れると、こうなります。
import requests
URL = "https://openapi.rakuten.co.jp/ichibams/api/IchibaItem/Search/20260701"
r = requests.get(
URL,
params={
"applicationId": APP_ID, # UUID形式
"affiliateId": AFFILIATE_ID, # xxxxxxxx.xxxxxxxx.xxxxxxxx.xxxxxxxx
"keyword": "エルゴトロン LX モニターアーム",
"hits": 3,
"format": "json",
},
headers={
"accessKey": ACCESS_KEY, # pk_ で始まる
"Origin": "https://yamasun-diy.com", # ★これが必須
},
timeout=30,
)実際に返ってきたものがこちら。
ヒット数: 652
- 【モニターアーム】エルゴトロン LX デスクマウント マットブラック 45-241-22
価格: 18,200円 / 店舗: エルゴトロン 楽天市場店
アフィリエイトURL: https://hb.afl.rakuten.co.jp/hgc/...
画像: https://thumbnail.image.rakuten.co.jp/@0_mall/ergotron/...商品名・価格・店舗名・画像URL・アフィリエイトリンクが、1回のリクエストで全部揃います。 記事に商品を載せるのに必要な情報は、これで全部そろいました。半日かけただけの価値はありました。
アプリ登録でハマりやすいポイント
コードより手前、管理画面での登録にも小さな地雷があります。
- アプリケーション名にハイフンが使えません。
yamasun-diyで登録しようとしたら「特殊文字を含めることはできません」で弾かれました。yamasundiyのように詰めれば通ります - 「許可されたウェブサイト」に自分のドメインを登録します。 ここに登録したドメインと、リクエストで送る
Originヘッダーが一致している必要があります。逆に言うと、Origin だけ直しても登録側が空なら通りません - APIアクセススコープは「楽天市場API」だけで足ります。 迷って全部チェックする必要はありません
- QPS(1秒あたりのリクエスト数)は 1 で十分でした。 記事1本あたり数回しか呼ばないので、上限を上げる必要はありませんでした
なお、こうした設定項目や上限値は時期・アカウントによって変わります。最新の値は必ず Rakuten Developers の管理画面とドキュメントでご確認ください。この記事の内容は2026年8月15日時点の実測です。
つまずいたポイントと、そこから得た教訓
エラーメッセージを信じすぎない
今回の3つのつまずきのうち、2つはエラーメッセージが原因を正しく指していませんでした。
- 「applicationIdが不正」→ 実際はエンドポイントが古い
- 「HTTP_REFERRERが無い」→ 実際に見ているのは
Origin
エラーメッセージは開発者が書いた文字列であって、その時点の実装を正確に反映しているとは限りません。特にAPIの仕様が大きく変わった直後は、メッセージだけ昔の名前で取り残されていることがあります。「言われたとおりに直したのに変わらない」が2回続いたら、メッセージ自体を疑うタイミングです。
総当たりは、恥ずかしい手段ではなく有効な手段
今回、最終的に正解にたどり着いたのは「ヘッダーとパラメータの候補を6通り、機械的に全部試した」からです。スマートな推理ではありません。
でも、ドキュメントに書かれていないことは、試すしかないんですよね。requests で書いたループを回して、返ってきたステータスコードを並べる。それだけで表が1枚できて、「Referer は関係ない」という事実がはっきりしました。悩んでいる時間より、試す時間のほうが安いです。
古い記事を鵜呑みにしない
楽天商品検索APIの解説記事はネット上に山ほどあります。ただ、その大半は旧エンドポイント・アプリIDのみの時代のもので、今のまま真似しても1行目で400が返ります。 私も最初の30分はそれで溶かしました。日付が入ったエンドポイント(/20220601 と /20260701)を見比べるのが、いちばん手っ取り早い鮮度チェックかもしれません。
まとめ
半日かけて分かったことを3行にすると、こうなります。
- エンドポイントは
https://openapi.rakuten.co.jp/ichibams/api/IchibaItem/Search/20260701 applicationIdに加えてaccessKey(pk_始まり)が要る- 403
HTTP_REFERRER_MISSINGの正解はOriginヘッダー(Refererは無関係)
たった3行です。でもこの3行がどこにも書かれていなかったので、この記事を書きました。同じところで止まっている人に届いたら本望です。
それにしても、Referer と Origin。この2つのヘッダーの名前を、今日ほどまじまじと見比べた日はありませんでした。
