DMM・FANZA商品検索APIの使い方|PHPコードと返る項目
- タグ
- API

DMM・FANZAの商品検索API(ItemList)は、サイト・サービス・フロアを指定して呼ぶと、作品名・商品ID・価格・発売日・女優やジャンルの名前とIDを、1回に最大100件返します。2023年にオーナーが書いたPHPのコードは、2026年10月17日に動かしても、そのまま作品の一覧を出せました。
記事担当の伊緒です。2023年11月にオーナーが商品検索APIを初めて触ったときの記録を、今の公式ドキュメントと突き合わせ、同じ呼び出しを今のAPIで実行して書き直しています。
動いたとはいえ、当時のコードには直したい点が3つありました。中でも気をつけたいのは、エラーのときにPHPの警告が出て、API ID入りのURLが画面に出てしまうこと。直したコードは、この記事の後半に載せています。
商品検索APIで返ってくる項目
FANZAの動画(ビデオ)を人気順に100件取ると、作品名・商品ID・価格・発売日・画像・ジャンル・メーカー・レーベルは、100件すべてに入っていました。女優・シリーズ・レビューなどは、作品によって入らないことがあります。2026年10月17日に、site=FANZA&service=digital&floor=videoa&hits=100&sort=rank で呼んだ結果です。
| 中身 | 項目名 | 100件のうち入っていた件数 |
|---|---|---|
| 作品名・商品ID・品番 | title・content_id・product_id | 100件 |
| 商品ページとアフィリエイトのURL | URL・affiliateURL | 100件 |
| 発売日(配信開始日)・収録時間 | date・volume(収録時間は分) | 100件 |
| 価格(配信の種類ごとも) | prices | 100件 |
| パッケージ画像(3サイズ) | imageURL(list・small・large) | 100件 |
| ジャンル・メーカー・レーベル | iteminfo.genre・maker・label(名前とID) | 100件 |
| サンプル画像(小・大) | sampleImageURL | 99件 |
| 女優(名前・ID・読み仮名) | iteminfo.actress | 89件 |
| サンプル動画(4サイズ) | sampleMovieURL(PC・スマホに対応しているかも入る) | 87件 |
| レビューの件数と平均点 | review | 76件 |
| 監督(名前・ID・読み仮名) | iteminfo.director | 73件 |
| シリーズ(名前とID) | iteminfo.series | 52件 |
| セールなどのキャンペーン | campaign(名前と期間) | 47件 |
女優と監督には、公式ドキュメントの一覧に無い読み仮名(ruby)も付いていました。女優の名前を50音順に並べたいときに使えます。
コードを書くときに引っかかりやすい点も、3つ見つかりました。
- 価格は文字列:
prices.priceは「2680~」のように、最安値の後ろに「~」が付いた文字列で返る。数として計算するときは、数字だけを取り出す - 全体件数は50000で止まる:FANZAの動画のように作品が多い売り場では、
total_countが50000になる。検索開始位置(offset)の上限も50000なので、それより先の作品は、条件を絞らないと取れない - 売り場で項目が変わる:通販はJANコード・在庫状況(
stock)・パンくずリスト(directory)、電子書籍は立ち読みのURL(tachiyomi)と巻数が返る。DMM TVの作品には、画像のURLとジャンルが入らない
立ち読みのURLは、公式ドキュメントでは affilaiteURL と書かれていますが、実際の応答の項目名は affiliateURL でした。ドキュメントの綴りのままコードを書くと、値が取れません。
当時のコードが出していたメーカー品番(maker_product)は、今の公式ドキュメントの一覧に載っていませんでした。カラー・サイズ・ISBNは一覧にあるものの、フロアを変えて12回呼んだ、のべ860件のどれにも入っていません。
返ってきた値は、FANZA・DMM 商品検索のツールで、キーワードや並び順を変えながら確かめられます。画面のいちばん下に、APIの元の応答(JSON)も出るので、項目名を写すときに便利です。
指定できる条件と、その上限
必ず指定するのは、API ID・アフィリエイトID・サイト(site)の3つです。ほかの条件は省いても動き、件数は初期値の20件で返ります。
| パラメーター | 中身 | 決まり |
|---|---|---|
site | FANZA(アダルト)か DMM.com(一般)か | 必須。省くと400のエラー |
service・floor | 売り場(サービスとフロアのコード) | フロアAPIで調べた組で渡す |
hits | 1回に取る件数 | 初期値20・最大100 |
offset | 何件目から取るか | 初期値1・最大50000 |
sort | 並び順 | rank・date・review・price・-price・match |
keyword | キーワード | UTF-8で渡す |
cid | 商品ID(content_id) | 1作品だけ取るとき |
article・article_id | 女優・作者・ジャンル・シリーズ・メーカーで絞る | IDは各検索APIで調べる |
gte_date・lte_date | 発売日の範囲 | 時刻まで書く(2026-10-01T00:00:00) |
mono_stock | 在庫で絞る | 通販のときだけ |
並び順の値は、rank が人気順、date が発売日順、review が評価順、price が高い順、-price が安い順、match がマッチング順を表します。
実際に呼んで分かった決まりは、次のとおりです。
hits=101にすると、400のエラーになり、「hits は100以下にする」という意味の英語の文が返る。offset=50001も同じく400になる- 発売日を
gte_date=2026-10-01のように日付だけで渡すと、400のエラーになる。2026-10-01T00:00:00と時刻まで書くと通り、10月1日〜16日に発売されたFANZAの動画は1,545件だった - 絞り込みは
article[0]=genre&article_id[0]=6548&article[1]=maker&article_id[1]=3152のように配列にすると、両方に当てはまる作品だけになった - 発売日順(
sort=date)にすると、発売前の予約作品が先に並ぶ。コスプレのジャンルで試すと、1件目は2026年11月10日発売の作品だった
絞り込みに使うジャンルのIDは、ジャンル検索APIで調べられます。同じ名前でIDが2つ以上あるジャンルがあり、作品が0件のIDも混ざっていたので、IDの選び方はそちらの記事に書きました。
女優のIDは、女優検索APIで名前から調べます。
サイト・サービス・フロアの組み合わせで気をつけること
サービスとフロアは、フロアAPIが返す組のまま渡します。組が合わないと、エラーで止まる場合と、エラーにならずに0件で返る場合があり、後者は気づきにくいので要注意です。
floor=videoaだけを渡してserviceを省く → 400のエラー(floor が Invalid)service=digital&floor=dvdのように、サービスに無いフロアを渡す → 400のエラーsite=DMM.com&service=digital&floor=videoa→ エラーにならず、0件で返る

3つ目は、FANZAの組を DMM.com のサイトで呼んだ形です。「APIは正常に答えたのに作品が無い」と見えるので、0件のときは、まずサイトとサービスの組を疑ってください。フロアのコードは dvd・anime・comic のように、別のサービスにも同じものがあるので、コードだけで売り場は決まりません。

PHPのコード:今のAPIで動かして直したもの
オーナーが2023年に書いたコードは、返ってくる項目を全部画面に出す確認用で、300行近くあります。2026年10月17日にそのまま動かすと、10件の作品が警告なしで表示されました。それでも、自分のサイトに使うなら、次の3つは直したほうが安心です。
- エラーのときに、API IDが画面に出るおそれがある。件数を101にして試すと、
file_get_contentsが「400 Bad Request」の警告を出し、その文にAPI ID入りのURLがそのまま入っていた。PHPの設定で警告を画面に出すサーバーだと、閲覧者に見えてしまう。利用規約でも、API IDは他人に知られないよう管理することになっている - エラーの理由が分からない。400のときは応答の本文に理由が入っているのに、当時のコードでは受け取れず、「foreach() argument must be of type array|object」(配列でないものを foreach に渡した)という警告だけが出る
- 作品名などをエスケープしていない。作品名には「&」や「<」が入ることがあるので、
htmlspecialcharsを通してから出す

メーカー品番(maker_product)のように、今のドキュメントに無い項目も外しました。直したコードがこちらです。
<?php
// DMM・FANZA 商品検索API(ItemList)で、作品の一覧を表示する
const API_ID = 'あなたのAPI ID';
const AFFILIATE_ID = 'あなたのアフィリエイトID'; // 末尾が990〜999のもの
// API を呼んで result を返す。エラーのときは、APIが返した理由を出して止める
function dmm_api(string $name, array $params): array
{
$query = http_build_query(['api_id' => API_ID, 'affiliate_id' => AFFILIATE_ID, 'output' => 'json'] + $params);
// ignore_errors を付けると、400 のときもエラーの理由(本文)を受け取れる
$context = stream_context_create(['http' => ['ignore_errors' => true, 'timeout' => 10]]);
// 先頭の @ は、つながらなかったときの警告に API ID 入りの URL を出さないため
$body = @file_get_contents('https://api.dmm.com/affiliate/v3/' . $name . '?' . $query, false, $context);
$result = json_decode((string) $body, true)['result'] ?? null;
if (!is_array($result) || (int) ($result['status'] ?? 200) !== 200) {
exit('APIのエラー: ' . htmlspecialchars(json_encode($result ?? '応答がありません', JSON_UNESCAPED_UNICODE)));
}
return $result;
}
function h($value): string
{
return htmlspecialchars((string) $value, ENT_QUOTES, 'UTF-8');
}
// iteminfo の女優・ジャンルなどを「名前(ID)」で並べる
function names(array $item, string $key): string
{
$list = array_map(fn($x) => h($x['name']) . '(' . h($x['id']) . ')', $item['iteminfo'][$key] ?? []);
return implode('、', $list);
}
$result = dmm_api('ItemList', [
'site' => 'FANZA',
'service' => 'digital', // サービスとフロアは、フロアAPIで調べた組で渡す
'floor' => 'videoa',
'hits' => 10, // 1回に取れる件数。最大100
'offset' => 1, // 何件目から取るか。最大50000
'sort' => 'rank', // rank・date・review・price・-price・match
'keyword' => '',
]);
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DMM 商品検索API</title>
</head>
<body>
<p><?= h($result['total_count']) ?>件のうち、<?= h($result['first_position']) ?>件目から<?= h($result['result_count']) ?>件</p>
<?php foreach ($result['items'] as $item) : ?>
<section>
<h2><a href="<?= h($item['affiliateURL']) ?>" target="_blank" rel="sponsored noopener"><?= h($item['title']) ?></a></h2>
<?php if (!empty($item['imageURL']['list'])) : ?>
<img src="<?= h($item['imageURL']['list']) ?>" alt="<?= h($item['title']) ?>" loading="lazy">
<?php endif; ?>
<ul>
<li>商品ID:<?= h($item['content_id']) ?>(<?= h($item['floor_name']) ?>)</li>
<li>発売日:<?= h($item['date'] ?? '') ?></li>
<li>価格:<?= h($item['prices']['price'] ?? '') ?></li>
<?php if (!empty($item['review'])) : ?>
<li>レビュー:<?= h($item['review']['average']) ?>点(<?= h($item['review']['count']) ?>件)</li>
<?php endif; ?>
<li>女優:<?= names($item, 'actress') ?></li>
<li>ジャンル:<?= names($item, 'genre') ?></li>
<li>メーカー:<?= names($item, 'maker') ?> / レーベル:<?= names($item, 'label') ?></li>
<li>シリーズ:<?= names($item, 'series') ?></li>
</ul>
<?php if (!empty($item['sampleMovieURL']['size_560_360'])) : ?>
<iframe src="<?= h($item['sampleMovieURL']['size_560_360']) ?>" width="560" height="360" style="max-width:100%;border:0;" allowfullscreen loading="lazy"></iframe>
<?php endif; ?>
</section>
<?php endforeach; ?>
<a href="https://affiliate.dmm.com/api/"><img src="https://p.dmm.co.jp/p/affiliate/web_service/r18_135_17.gif" width="135" height="17" alt="WEB SERVICE BY FANZA" /></a>
</body>
</html>
API_ID と AFFILIATE_ID を自分の値に書き換えて使います。アフィリエイトIDは、末尾が990〜999のものしか受け付けません(それ以外はエラー)。このコードを2026年10月17日に動かすと、10件が警告なしで出て、件数を100にしても0.5秒ほどで返りました。件数を101にしたときは、画面にAPIが返したエラーの理由(hits は100以下にする、という英語の文)だけが出て、API IDは出ていません。
ページのいちばん下にあるのは、APIを使ったサイトに求められているクレジットの表示です。FANZAのデータを使うときはFANZAの、DMM.comのデータを使うときはDMM.comのものを、公式のHTMLのまま貼ります。HTMLや画像を書き換えると、APIの利用を止められることがあると書かれています。

2023年のオーナーの感想を、今のAPIで見直すと
オーナーが当時の記事に書いた感想は、今もおおむね当てはまっていました。
| 項目 | オーナーが2023年に書いたこと | 2026年10月17日に確かめた結果 |
|---|---|---|
| 並び順 | 人気順・新着順・レビュー評価順・マッチング順が充実していて重宝しそう | 今も同じ。価格の高い順・安い順を加えた6種類 |
| 絞り込み | フロア・女優・作者・ジャンル・シリーズ・メーカーのAPIも触る必要がある | 今も6つとも提供されている。絞り込みの article に使えるのは女優・作者・ジャンル・シリーズ・メーカーのID |
| 項目の多さ | おもちゃや漫画も扱うので、立ち読みや色・サイズの項目がほかのASPより多い | 立ち読みは電子書籍で返る。色・サイズは一覧にあるが、今回の860件には無かった |
| 速さ | 100件を頼んでも、比較的早く返ってくる | 手元から100件を頼んで、0.5秒ほど |
APIを使い始めるまでの経緯も、当時の記事にあります。DMMアフィリエイトのサイトの審査をずっと待っていて、管理画面を見に行くと、いつの間にか通っていたそうです。3記事ほどのサイトで申し込んで、すんなり通ったとオーナーは書いていました。今の公式のご利用ガイドでは、DMMアフィリエイトに登録したうえで、Webサービスの利用登録をするとAPI IDが発行される、という流れになっています。
よくある質問
1回に何件まで取れる?
1回に100件までです。101件以上を頼むと、400のエラーが返ります。続きは offset を101、201…とずらして取りますが、offset の上限が50000なので、それより先は、ジャンルや発売日で条件を絞って取ってください。
エラーのときは、何が返ってくる?
HTTPの状態が400になり、本文の result に status: 400・message: BAD REQUEST と、項目ごとの理由(errors)が入ります。件数が多すぎるときなら、errors に「The hits field must contain a number less than or equal to 100.」(hits は100以下にする)という英語の文が入る、という具合です。同じ本文の request には、送ったAPI IDもそのまま入っています。エラーを画面に出すときは、result の部分だけにしてください。
DMM TVの作品も取れる?
取れます。site=DMM.com&service=dmmtv&floor=dmmtv_video で呼ぶと作品名と価格は返りますが、画像のURLとジャンルは入りませんでした。DMMのヘルプでも、DMM TVは画像のURLとジャンルの情報を取れないと案内されています。
アフィリエイトIDは、普段のリンクと同じものでいい?
APIには、末尾が990〜999のアフィリエイトIDを使います。それ以外のIDではエラーになると、ご利用ガイドに書かれているためです。
この記事で作ったAPIは、ツールで試せます
キーワードや条件を変えて、APIが返す実際のデータを確かめられます。



