Webサイト

CC/PPとは?RDFで端末情報を送るW3C仕様の構造とClient Hintsへの移行

CC/PPとは?RDFで端末情報を送るW3C仕様の構造とClient Hintsへの移行

CC/PP(Composite Capability/Preference Profiles)は、端末の画面サイズや対応形式といった「能力」と、利用者の「好み」をRDFで記述し、サーバーがコンテンツを端末に合わせて出し分けるためのW3C仕様です。Structure and Vocabularies 1.0が2004年1月15日に勧告になりました。ただし、仕様が勧告になったこととブラウザが実装したことは別で、PC向けの主要ブラウザで広く使われる送信手段にはなりませんでした。2.0は2010年に勧告へ届かないまま打ち切られています。

この記事では、仕様の版と現在の位置づけを確認したうえで、プロファイルの構造、HTTPでの送り方、Pythonのrdflibで実際に読む手順を順に説明します。最後に、いま同じ目的を果たすClient Hintsやメディアクエリとの対応を示します。

まとめ:CC/PPの要点と現在の位置づけ

  • CC/PPは、端末の能力と利用者の好みをまとめた「デリバリーコンテキスト」を、RDFのプロファイルとして記述する仕組み
  • W3Cの正式な勧告は2004年1月15日のStructure and Vocabularies 1.0だけ。2.0は2010年6月29日にWorking Group Noteとして打ち切られた。1.1は2004年の作業計画にあった名前で、公開された版ではない
  • プロファイルは「プロファイル→コンポーネント→属性」の2階層で、ccpp:defaultsで既定値を参照し、直接書いた値で上書きする
  • 1.0自体は送信プロトコルを定めていない。HTTPで送る方式は1999年のW3C Note(Profileヘッダー)と、携帯電話向けのUAProf(x-wap-profileヘッダー)に分かれた
  • 新しいシステムでCC/PPを採用する理由は無い。サーバー側の出し分けにはClient Hints、表示の調整にはメディアクエリを使う

古い携帯向けシステムの保守でUAProfのデータを読む場合や、仕様の経緯を調べる場合は、以降の各章で詳しく扱います。

CC/PPの定義と仕様の版:1.0勧告と2.0の打ち切り

CC/PP 1.0の仕様書は、プロファイルを「端末の能力と利用者の好みの記述」と定義しています。これをデバイスの「デリバリーコンテキスト」と呼び、端末に提示するコンテンツの適応に使うとしています。名前の「Composite」は、ハードウェア・ソフトウェア・ブラウザといった複数の部品の記述を1つのプロファイルに束ねることを指します。

1990年代末、Webを見る端末はPCだけではなくなりました。携帯電話やPDAが現れ、画面の大きさも対応する形式もまちまちになったためです。仕様書の序文は、既存の手段としてHTTPのaccept系ヘッダーとHTMLのalt属性を挙げ、どちらも限定的だと書いています。そのうえで、より汎用的なプロファイル形式が必要だと述べています。

文書 種別 日付
CC/PP exchange protocol(HTTP Extension Framework版) W3C Note 1999年6月24日
CC/PP Structure and Vocabularies 1.0 W3C勧告 2004年1月15日
CC/PP Structure and Vocabularies 2.0 Working Draft 2007年4月30日
同 2.0(最終) Working Group Note 2010年6月29日

2.0は、RDFの改訂に合わせて1.0を作り直す版でした。ただし、2010年の最終版の「Status of this document」には、Ubiquitous Web Applications Working Groupの閉鎖に伴って打ち切られたと書かれています。勧告として確定した内容を引くときはCC/PP 1.0を、改訂の検討内容を参照するときは2.0のNoteを、それぞれ出典にしてください。

「CC/PP 1.0から1.1へ進化した」という説明を見かけることがありますが、W3Cの技術文書一覧にある関連文書は、1.0、Implementors Guide、1999年のNote、2.0だけです。1.1は、2004年のDevice Independence Working Groupの憲章に作業項目「CC/PP Structure and Vocabularies Version 1.1」として載った計画名で、仕様としては公開されていません。RDFの改訂を取り込むというその目的は、2.0の草案に引き継がれました。

CC/PPプロファイルの構造:component・属性・defaults

プロファイル・コンポーネント・属性の2階層

CC/PPのプロファイルは、プロファイルの下に1つ以上のccpp:componentを置き、各コンポーネントに属性(attribute)を並べる2階層の構造です。仕様の例では、コンポーネントをTerminalHardware(端末のハードウェア)、TerminalSoftware(OS)、TerminalBrowser(ブラウザ)の3つに分けています。コンポーネントの種類はrdf:typeで示します。

次の例は、仕様の図2-4(既定値の上書き)を短く整えたものです。中核構造の名前空間はhttp://www.w3.org/2002/11/08-ccpp-schema#です。prf:は、仕様の例で使われている架空のボキャブラリです。

<?xml version="1.0"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:ccpp="http://www.w3.org/2002/11/08-ccpp-schema#"
         xmlns:prf="http://example.com/Schema#">
  <rdf:Description rdf:about="http://example.com/MyProfile">
    <ccpp:component>
      <rdf:Description rdf:about="http://example.com/TerminalHardware">
        <rdf:type rdf:resource="http://example.com/Schema#HardwarePlatform"/>
        <ccpp:defaults rdf:resource="http://example.com/HWDefault"/>
        <prf:displayWidth>640</prf:displayWidth>
        <prf:displayHeight>400</prf:displayHeight>
      </rdf:Description>
    </ccpp:component>
  </rdf:Description>
</rdf:RDF>

シリアライズ形式としてRDF/XMLが推奨されています。仕様は他のRDF形式を禁止してはいませんが、その解釈の指針は示していません。

defaultsによる既定値の参照と上書きの規則

端末ごとに全属性を書くと、プロファイルが長くなります。そこで、コンポーネントはccpp:defaultsで別のリソースに置いた既定値を参照できます。上の例のHWDefaultは、メーカーなどが別のURLで公開する想定の文書で、中身は次のとおりです。

<?xml version="1.0"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
         xmlns:prf="http://example.com/Schema#">
  <rdf:Description rdf:about="http://example.com/HWDefault">
    <rdf:type rdf:resource="http://example.com/Schema#HardwarePlatform"/>
    <prf:cpu>PPC</prf:cpu>
    <prf:displayWidth>320</prf:displayWidth>
    <prf:displayHeight>200</prf:displayHeight>
  </rdf:Description>
</rdf:RDF>

同じ属性が既定値とコンポーネントの両方にある場合の扱いを、仕様のdefaultsの節は「the directly applied value takes precedence」と定めています。つまり直接書いた値が優先です。この例で有効になる値は、cpuが既定値のPPC、displayWidthとdisplayHeightが上書き後の640と400です。メーカーが機種の共通値を公開し、端末は差分だけを送る。これがdefaultsの狙いで、後述するUAProfのx-wap-profile-diffも同じ発想です。

名前空間とボキャブラリ:ccpp-clientとUAProf

CC/PP 1.0が定めているのは構造だけで、「画面幅」のような個々の属性の名前は、ボキャブラリとして別に定義します。仕様の付録Cは、印刷・表示する端末向けの任意の語彙(名前空間http://www.w3.org/2002/11/08-ccpp-client)を示しています。IETFのメディア特性登録(CONNEG)の成果を元にしたもので、属性は次の9つしかありません。

  • deviceIdentifier・type・schema:端末の識別子と、受け付けるメディアタイプ・スキーマ
  • charWidth・charHeight・charset:文字表示の桁数・行数と文字コード
  • pix-x・pix-y・color:画面のピクセル数と色の能力

実際の携帯電話で使われたのは、WAP Forum(のちのOpen Mobile Alliance)のUAProfのボキャブラリです。UAProfでは画面サイズをScreenSizeに320x200のような文字列で書き、OS名はOSNameに書きます。仕様書は、CC/PPがUAProfの既存プロファイルを受け入れられるよう設計したと明記しています。

CC/PPをHTTPで送る方式:exchange protocolとUAProf

CC/PP 1.0は送信プロトコルを定めていません。付録Fは「これはプロトコル仕様ではない」と断ったうえで、送り方の流れだけを示しています。クライアントがプロファイル(既定値への参照と差分)を付けてリクエストし、途中のプロキシが自分の制約を足して、オリジンサーバーが最終的なプロファイルで応答を作る、という流れです。

Profileヘッダーで参照と差分を送るexchange protocolとHTTP拡張への依存

1999年6月24日のNote「CC/PP exchange protocol based on HTTP Extension Framework」は、ProfileリクエストヘッダーでプロファイルのURLと差分の識別子を送る方式を提案しました。応答側ではProfile-warningヘッダーで警告を返します。Noteに載っているヘッダーの例は次のとおりです。

Profile: "http://www.aaa.com/hw","1-uKhJE/AEeeMzFSejsYshHg==","http://www.bbb.com/sw"

この方式はHTTP Extension Framework(RFC 2774)に依存していました。W3Cは2004年のDevice Independence Working Groupの憲章で、この提案が「HTTP-exの支持不足のため成功しなかった」と総括しています。

UAProfのx-wap-profileによるプロファイルURLと差分の送信

実際に携帯電話で動いたのは、OMAのUAProfが定めたx-wap-profileです。UAProf 2.0の仕様書は、これを「CPI(端末の能力と好みの情報)を指すURI、x-wap-profile-diffで運ぶ差分への参照、またはその組み合わせ」を入れる汎用ヘッダーと定義しています。仕様書の例を整えると、次のようになります。

GET http://anyuri/ HTTP/1.1
Host: plaintext
x-wap-profile: "http://profilerepository/", "1-uKdjJHuhjHUuj"
x-wap-profile-diff: 1; <?xml ... ?>

HTTP/1.1 200 OK
x-wap-profile-warning: 202

この方式では、サーバーはURLの先にあるRDF/XMLを取りに行き、パースし、差分を重ねてから出し分けを決めます。プロファイルを公開するリポジトリが応答しなければ判定できないので、取得結果をキャッシュするか、機種ごとの値を自前で持つ設計が要ります。

rdflibでCC/PPプロファイルを読む手順

保守中の携帯向けシステムでUAProfファイルを読み直す場面や、仕様の例を動かして挙動を確かめたい場面では、RDFライブラリでパースしてから既定値を解決するのが確実です。ここでは、上の2つのファイル(profile.rdfとhwdefault.rdf)を同じディレクトリに置き、Pythonのrdflibで有効値を求めます。

from rdflib import Graph, Namespace, RDF

CCPP = Namespace("http://www.w3.org/2002/11/08-ccpp-schema#")

g = Graph()
g.parse("profile.rdf", format="xml")
g.parse("hwdefault.rdf", format="xml")

for profile, _, comp in g.triples((None, CCPP.component, None)):
    effective = {}
    # 1. defaults が指す既定値を先に入れる
    for d in g.objects(comp, CCPP.defaults):
        for p, o in g.predicate_objects(d):
            if p != RDF.type:
                effective[p.split("#")[-1]] = str(o)
    # 2. コンポーネントに直接書かれた値で上書きする
    for p, o in g.predicate_objects(comp):
        if p not in (RDF.type, CCPP.defaults):
            effective[p.split("#")[-1]] = str(o)
    print(comp, effective)

rdflib 7.6.0とPython 3.12でこのスクリプトを実行した出力が、次のとおりです(2026年10月7日に実行)。

$ uv run --python 3.12 --with rdflib==7.6.0 python resolve.py
http://example.com/TerminalHardware {'cpu': 'PPC', 'displayWidth': '640', 'displayHeight': '400'}

cpuは既定値から、画面サイズは直接書いた値から取られ、仕様の優先順位どおりの結果になりました。このコードは掲載例を確かめるための簡易版で、属性名の#より後ろだけを辞書のキーにしています。別の名前空間に同じ名前の属性があると上書きされるため、実用では完全な属性URIをキーにしてください。ほかに気をつける点は次のとおりです。

  • このサンプルはstr(o)で値を文字列にそろえている。displayWidthを数値として比べるなら、int()への変換を自分で加える
  • rdf:Bagで書かれた複数値の属性(例:対応HTMLバージョン)は、パース後のグラフではrdf:liではなくrdf:_1・rdf:_2という述語になっている。値はBagのノードからこれらをたどって取り出す
  • defaultsが外部URLの場合、そのURLを取得してグラフに読み込まないと既定値が欠ける。公開元のURLが今も応答するとは限らない

Javaの場合は、JCPのJSR 188「CC/PP Processing」が2003年10月30日にFinal Releaseになっています。HPによるオープンソースの実験的実装DELIもありました。どちらも2000年代の成果物なので、今から依存先に選ぶより、上の例のように汎用のRDFライブラリで必要な属性だけを読むほうが保守しやすくなります。RDFのトリプルや語彙の基礎はRDFとOWLでオントロジーを定義する手順で扱っています。

CC/PPが普及しなかった背景:送信方式の未確立と端末情報の送信コスト

一次資料で確認できる直接の事情は、送り方が標準にならなかったことです。W3Cは2004年の憲章で、exchange protocolが土台のHTTP Extension Frameworkの支持不足で成功しなかったと記録しています。同じ憲章は、OMAがUAProf版のCC/PPを運ぶ独自のHTTP拡張ヘッダーを作ったことにも触れています。

端末情報を要求の前から送る方式そのものにも課題があります。RFC 8942は、HTTPの先行型のコンテンツネゴシエーション一般について、要旨で「ユーザーエージェントはこうしたリクエストヘッダーを送りたがらない。使われるか分からず、性能とプライバシーの両方に負担がかかるからだ」と書いています。CC/PPを名指しした分析ではありませんが、同じ構図に当てはまります。

外部の既定値を使う構成では、実装の負担も増えます。出し分けの前に、外部URLの取得、XMLのパース、defaultsの解決が必要です。キャッシュで外部取得を省くこともできますが、その分の管理が要ります。W3Cはその後、端末情報をサーバー側のリポジトリから引くDevice Description Repository Simple APIを2008年12月5日に勧告にしました。ブラウザが情報を送るのではなく、サーバーが調べる方向の仕様です。デリバリーコンテキストの形式モデルを定めるDelivery Context Ontologyは、CC/PP 2.0と同じ2010年6月29日にWorking Group Noteとなり、同じくUbiquitous Web Applications Working Groupの閉鎖に伴って打ち切られました。

端末の詳しい情報を常に送る仕組みは、今の基準でいえば、ブラウザのフィンガープリントの材料を増やすことにもなります。Client Hintsは、送る情報を絞り、サーバーが必要なものだけを要求する設計で、この負担を避けています。

CC/PPの代替技術との対応:Client Hintsとメディアクエリ

CC/PPの要素と現在の技術の対応表

CC/PPでの扱い 現在の手段 仕様の状況
RDFプロファイル・参照先・差分 Accept-CHで追加ヒントを要求 RFC 8942(Experimental・2021年2月)
端末種別・OS Sec-CH-UA-Mobile・Sec-CH-UA-Platform WICG草案(Community Group Report)
画面サイズ(pix-x・pix-y) CSSメディアクエリ・img要素のsrcset HTML・CSS標準
対応するメディア形式(type) Acceptヘッダー HTTP標準(RFC 9110)
利用者の好み prefers-color-scheme等のメディア特性 CSS Media Queries Level 5

違いは、何を誰が決めるかです。CC/PPは端末の能力をRDFで記述する仕様で、送る側は参照先のURLや差分を組み合わせてプロファイルを伝えます。RFC 8942では、サーバーがAccept-CH応答ヘッダーで欲しいヒントを宣言し、ブラウザはそれを見て個別のヘッダーを付けます。User-Agent Client Hintsでは、Sec-CH-UA・Sec-CH-UA-Mobile・Sec-CH-UA-Platformの3つが「low entropy」として要求なしでも送られます。機種名やOSの細かい版は、HTTPSの接続で、サーバーが要求し、Permissions Policyで送信が許可されている場合に限って届きます。要求しても必ず返るとは限りません。次の例は、こうした条件を満たした同一オリジンへのリクエストで、値はAndroid端末を想定したものです。

# 1回目の応答:サーバーが欲しいヒントを宣言する
HTTP/1.1 200 OK
Accept-CH: Sec-CH-UA-Model, Sec-CH-UA-Platform-Version

# 次のリクエスト:既定の3項目+要求された2項目が付く
GET /page HTTP/1.1
Sec-CH-UA: "Chromium";v="150", "Google Chrome";v="150", "Not.A/Brand";v="99"
Sec-CH-UA-Mobile: ?1
Sec-CH-UA-Platform: "Android"
Sec-CH-UA-Model: "Pixel 9"
Sec-CH-UA-Platform-Version: "15.0.0"

メディア形式(Accept)や圧縮形式(Accept-Encoding)のように、HTTPのヘッダーでもともと交渉できる項目もあります。圧縮形式の交渉はAccept-Encodingの指定とContent-Encodingとの違いで詳しく扱っています。一方、文字コードを交渉するAccept-Charsetは、UTF-8がほぼ普及したことを理由にRFC 9110で非推奨になっています。

Client Hintsでも足りない場面と採用を避ける条件

MDNのブラウザ互換性データでは、Sec-CH-UAはChrome 89以降とEdgeが対応し、FirefoxとSafariは未対応です。Client Hintsだけで端末を出し分ける設計にすると、iPhoneのSafariからのリクエストには何も届きません。新規に作る場合の判断は次のとおりです。

  • 表示の崩れを防ぐ目的なら、サーバー側で判定せず、レスポンシブデザイン(メディアクエリとsrcset)で解決する
  • 配信する画像の形式はAcceptヘッダーで判断する。端末の種別やOSで分けたい場合(アプリストアへの誘導など)はClient Hintsを使い、値が届かないときは共通の内容を返すか、利用者に選ばせる。User-Agent文字列の解析は、それでも足りない場合の補助にとどめる
  • CC/PP・UAProfを新たに組み込むのは避ける。送ってくるブラウザが無く、2.0も打ち切られているため、受け口を作っても使われない

例外は、UAProfのURLを送ってくる古いフィーチャーフォンや組み込み端末を、今も相手にしているシステムです。その場合も、URLの先を毎回取りに行かず、機種ごとの値を自前の表に持ち、x-wap-profileは表を引くキーとしてだけ使う設計にしてください。

CC/PPについてよくある質問

CC/PPの正式名称と読み方は何ですか?

正式名称はComposite Capability/Preference Profilesです。直訳すると「複合的な能力・好みのプロファイル」で、一般には「シーシーピーピー」と読みます。

CC/PPは現在も使われていますか?

W3Cの勧告は2004年の1.0のままで、2.0は2010年に打ち切られ、仕様の作業は止まっています。保守中のシステムに関わる場合は、リクエストログにx-wap-profileヘッダーが届いているか、その値を判定に使っている処理があるかを確かめてください。届いていなければ、その処理は外せます。

CC/PPとUAProfの違いは何ですか?

CC/PPは、W3Cが定めたプロファイルの構造(RDFでの書き方)です。UAProfは、OMAがCC/PPのモデルを使って携帯電話向けの語彙と送信ヘッダー(x-wap-profile)まで定めた仕様です。実際の端末で使われたのはUAProfのほうでした。

CC/PP 2.0はW3C勧告になりましたか?

なっていません。2007年4月30日のWorking Draftの後、2010年6月29日にWorking Group Noteとして公開され、Ubiquitous Web Applications Working Groupの閉鎖に伴って打ち切られました。

CC/PPとUser-Agent Client Hintsは何が違いますか?

CC/PPは端末の能力と好みをRDFで記述する仕様で、プロファイル本体のほか、参照先のURLや差分で伝えることもできます。User-Agent Client Hintsは、サーバーがAccept-CHで要求した項目だけを、ブラウザが個別のHTTPヘッダーで返します。既定で送られるのはブランド・モバイルかどうか・プラットフォームの3項目に限られます。

関連記事

お気に入りに入れた記事の一覧

資料請求

今日のトレンド記事 直近 24 時間で、いつもより多く読まれている記事

  1. 2026.10.23 テックブログ Renta!不正アクセスでサービス停止:再開未定の現状と運営側の停止判断・証拠保全・段階的再開
  2. 2025.01.09 コラム アドレサブルCM(Addressable CM)とは?フジテレビで出る表示の意味・仕組みと視聴データの扱い
  3. 2026.07.09 テックブログ Muse Imageとは?Metaの画像生成AIの使い方・API料金(1枚0.01ドル)と日本での提供状況【2026年10月】
  4. 2025.12.10 コラム 今の50代は何世代?バブル世代・団塊ジュニア・氷河期の境目と特徴
  5. 2026.10.21 テックブログ ふるさとチョイス不正アクセスで445万件流出:パスワード変更・対象確認と再開時期(10月23日第2報まで)

RELATED POSTS 関連記事

目次