Contents
1. Unsplash API の概要
Unsplash は「5,000 万点以上」の高品質フリー画像を提供するプラットフォームです。
API を使うことで、以下のような操作をプログラムから直接実行できます。
| 用途 | 主なエンドポイント |
|---|---|
| キーワード検索 | /search/photos |
| ランダム取得 | /photos/random |
| コレクション一覧・取得 | /collections |
| 写真の詳細情報取得 | /photos/:id |
商用利用について
画像は「無料」で商用プロジェクトでも使用可能ですが、必ず クレジット表記(Photo by <作者> on Unsplash) を行う必要があります。
2. アカウント作成と Access Key / Secret Key の取得手順
- Unsplash にサインアップ
-
https://unsplash.com/ja にアクセスし、メールアドレスまたは SNS アカウントで登録。
-
Developers ダッシュボードへ移動
-
ログイン後、右上メニューの「Developers」→「Your Applications」をクリック。
-
新規アプリケーションを作成
-
「Create a new application」ボタンを押し、以下を入力。2024 年版では 「利用目的(Purpose)」は任意ですが、将来的に必須になる可能性があるため具体的に記入しておくことを推奨 します。
- アプリ名
- 説明(英語推奨)
- 用途(例:Web フロントエンドでの画像表示)
-
キーの発行
- 作成完了後に Access Key と Secret Key が表示されます。
- 「Show Secret」ボタンは最初の表示だけ有効ですので、必ず安全な場所へコピーして保存してください。
ベストプラクティス:キーは
.env等の環境変数ファイルに格納し、.gitignoreでリポジトリから除外します。
3. 認証方式と主要エンドポイントの解説
3‑1. 認証方式
| 方法 | 用途 | 実装例 |
|---|---|---|
| Client ID(Access Key) | 読み取り系リクエスト(検索・取得)全般 | GET https://api.unsplash.com/photos/random?client_id=YOUR_ACCESS_KEY |
| OAuth 2.0 Authorization Code Grant | 書き込み系 API(コレクション作成、写真のいいね等) | 詳細は下記フローを参照 |
OAuth 2.0 基本フロー(Authorization Code Grant)
- ユーザーを
https://unsplash.com/oauth/authorizeにリダイレクトし、client_id,redirect_uri,response_type=code,scope=public+write_photos等のパラメータを付与。 - ユーザーが認可すると 認可コード が
redirect_uriのクエリに返る。 - サーバ側で次の POST リクエストを送信し、アクセストークンを取得する。
|
1 2 3 4 5 6 7 8 9 10 11 |
POST https://unsplash.com/oauth/token Content-Type: application/json { "client_id": "YOUR_ACCESS_KEY", "client_secret": "YOUR_SECRET_KEY", "code": "AUTHORIZATION_CODE", "grant_type": "authorization_code", "redirect_uri": "https://yourapp.example.com/callback" } |
取得したアクセストークンは Authorization: Bearer <TOKEN> ヘッダーで送信します。
3‑2. 主なエンドポイントとリクエスト例
| エンドポイント | 説明 | 主なパラメータ | サンプル URL |
|---|---|---|---|
/search/photos |
キーワード検索 | query, page, per_page, orientation |
https://api.unsplash.com/search/photos?query=mountain&page=1&per_page=10&client_id=YOUR_ACCESS_KEY |
/photos/random |
ランダム取得(複数枚可) | count, query, orientation |
https://api.unsplash.com/photos/random?count=5&query=city&client_id=YOUR_ACCESS_KEY |
/collections/:id/photos |
コレクション内の画像一覧 | page, per_page |
https://api.unsplash.com/collections/12345/photos?page=1&per_page=15&client_id=YOUR_ACCESS_KEY |
/photos/:id/download |
画像ダウンロードリンク取得(トラッキング付き) | — | https://api.unsplash.com/photos/abcde/download?client_id=YOUR_ACCESS_KEY |
サイズ指定の正しい書き方
Unsplash の画像 URL に対しては、クエリパラメータで任意のサイズやフォーマットを付与できます。例:https://images.unsplash.com/photo-xxxxxx?w=800&h=600&fit=crop&fm=jpg。公式ドキュメントでは?w=のみならず、&h=,&fit=,&fm=などを組み合わせることで目的の画像を取得できます。
4. 実装ハンズオン
4‑1. Vite + React(フロントエンド)
プロジェクト作成 & 環境変数設定
|
1 2 3 4 5 6 |
npm create vite@latest unsplash-demo -- --template react cd unsplash-demo npm install # .env に Access Key を保存(.gitignore で除外済みと想定) echo "VITE_UNSPLASH_ACCESS_KEY=YOUR_ACCESS_KEY" >> .env |
ランダム画像取得コンポーネント
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
// src/components/RandomImage.tsx import { useEffect, useState } from "react"; type UnsplashPhoto = { urls: { regular: string; raw: string }; alt_description: string | null; user: { name: string; links: { html: string } }; }; export default function RandomImage() { const [photo, setPhoto] = useState<UnsplashPhoto | null>(null); const [error, setError] = useState<string>(""); useEffect(() => { const fetchRandom = async () => { try { const resp = await fetch( `https://api.unsplash.com/photos/random?client_id=${import.meta.env.VITE_UNSPLASH_ACCESS_KEY}&w=800` ); if (!resp.ok) throw new Error(`HTTP ${resp.status}`); const data: UnsplashPhoto = await resp.json(); setPhoto(data); } catch (e:any) { setError(e.message); } }; fetchRandom(); }, []); if (error) return <p>画像取得失敗: {error}</p>; if (!photo) return <p>読み込み中…</p>; const credit = ( <figcaption style={{ fontSize: "0.85rem", marginTop: "0.5rem" }}> Photo by{" "} <a href={photo.user.links.html} target="_blank" rel="noopener"> {photo.user.name} </a>{" "} on{" "} <a href="https://unsplash.com" target="_blank" rel="noopener"> Unsplash </a> </figcaption> ); return ( <figure> <img src={photo.urls.regular} alt={photo.alt_description ?? "Unsplash random"} style={{ maxWidth: "100%", height: "auto", borderRadius: "4px" }} /> {credit} </figure> ); } |
App.tsx に <RandomImage /> を配置すれば、開発サーバ (npm run dev) 起動時にランダム画像が表示されます。
4‑2. Python(データセット取得)
正しいサイズ指定例
Unsplash の画像 URL へは ?w= に加えて &fit=crop&fm=jpg などを付与すると、転送量の削減やフォーマット統一が可能です。以下は「猫」キーワードで 10 枚取得し、幅 400px の JPEG を保存するサンプルです。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# unsplash_cats.py import os import requests from pathlib import Path ACCESS_KEY = os.getenv("UNSPLASH_ACCESS_KEY") if not ACCESS_KEY: raise RuntimeError("環境変数 UNSPLASH_ACCESS_KEY が設定されていません") SAVE_DIR = Path("./cat_images") SAVE_DIR.mkdir(exist_ok=True) def download_random_cats(count: int = 10): endpoint = "https://api.unsplash.com/photos/random" params = { "query": "cat", "count": count, "client_id": ACCESS_KEY, # 幅 400px、JPEG に変換し、必要に応じてトリミング "w": 400, "fm": "jpg", "fit": "crop" } resp = requests.get(endpoint, params=params) resp.raise_for_status() photos = resp.json() # count が 1 のときは dict、複数のときは list if isinstance(photos, dict): photos = [photos] for i, photo in enumerate(photos, start=1): img_url = f"{photo['urls']['raw']}?w=400&fm=jpg&fit=crop" img_resp = requests.get(img_url) img_resp.raise_for_status() path = SAVE_DIR / f"cat_{i}.jpg" with open(path, "wb") as fp: fp.write(img_resp.content) print(f"保存: {path}") if __name__ == "__main__": download_random_cats() |
実行手順(Linux/macOS):
|
1 2 3 |
export UNSPLASH_ACCESS_KEY=YOUR_ACCESS_KEY python unsplash_cats.py |
5. 運用・ベストプラクティス
5‑1. レートリミットとエラーハンドリング
| 項目 | 現行(2024‑06) |
|---|---|
| 認証済みリクエスト上限 | 約 50 リクエスト/分(公式ドキュメントで最新数値を必ず確認) |
| 未認証リクエスト上限 | 約 5 リクエスト/分 |
Exponential Backoff の実装例(JavaScript)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
async function fetchWithRetry(url, attempts = 4, delayMs = 500) { try { const res = await fetch(url); if (res.status === 429 && attempts > 0) { await new Promise(r => setTimeout(r, delayMs)); return fetchWithRetry(url, attempts - 1, delayMs * 2); } return res; } catch (e) { throw e; } } |
5‑2. キャッシュ活用と画像サイズ最適化
- ブラウザキャッシュ:
Cache-Control: max-age=86400が付与された場合は、同一 URL の再取得を避ける。 - サーバ側プロキシ:Next.js や Vercel で
image optimizationを利用すれば、サイズ変換を CDN 側で完結でき、API 呼び出し回数が削減されます。
5‑3. キー管理の徹底
| 手段 | メリット |
|---|---|
.env + .gitignore |
ソースコードからキーを除外 |
| CI/CD シークレットストア(GitHub Actions, Vercel, Netlify) | ビルド時に自動注入、漏洩リスク低減 |
| 環境別 Access Key の発行 | 開発・ステージング・本番でキーを分離し、権限範囲も個別管理できる |
5‑4. クレジット表記の自動化
- HTML:
<a href="{photo.user.links.html}" target="_blank">Photo by {photo.user.name}</a> - React コンポーネントや Python スクリプト のコメントに必ず出力し、画像保存時にもメタ情報として残すと管理が楽です。
6. FAQ(よくある質問)
| 質問 | 回答 |
|---|---|
| 400 Bad Request が返ってきた | パラメータ名のスペルミスや必須パラメータ未指定。公式サンプルと照らし合わせて確認してください。 |
| 401 Unauthorized | Access Key が無効、または環境変数に正しく設定されていません。ダッシュボードでキーが有効か確認し、.env の記述ミスもチェック。 |
| 403 Forbidden | 利用規約違反(例:画像の加工後再配布)や、非公開コレクションへアクセスしようとしている可能性があります。目的と権限を見直してください。 |
| 429 Too Many Requests | レートリミット超過です。バックオフ実装とキャッシュ戦略でリクエスト頻度を下げましょう。 |
| OAuth のトークンが取得できない | redirect_uri がダッシュボードに登録されていない、または client_secret が間違っているケースが多いです。設定画面とコードを再確認してください。 |
7. まとめ
Unsplash API は 高品質なフリー画像 を手軽に取得できる強力なツールです。実装のポイントは次の通りです。
- 公式ドキュメントを常に最新情報として参照(レートリミット・必須パラメータは変動する)。
- Access Key は環境変数で安全管理し、キー漏洩対策を徹底。
- 読み取り系は client_id、書き込み系は OAuth 2.0 を使い分ける。
- 画像サイズやフォーマットは
?w=...&h=...&fit=...&fm=...の組み合わせで最適化し、転送量とリクエスト数を削減。 - レートリミット超過時は Exponential Backoff とキャッシュ活用で安定運用。
- クレジット表記は必須。コード内に自動生成ロジックを組み込み、利用規約違反を防止する。
これらのベストプラクティスを守れば、フロントエンド・バックエンド問わず安全かつ効率的に Unsplash の画像リソースを活用できます。Happy coding!