Contents
Pexels API キーの取得方法
Pexels の開発者向けページから API キーを取得する手順は、公式ドキュメントに記載されている通り数クリックで完了します。キーが必要になるタイミングは、画像や動画をプログラムから取得したい直前ですので、事前に取得して安全な場所に保管しておくことが重要です。本節では、公式サイトの最新 UI(2024 年 10 月時点)に基づいた手順をまとめます。
- Pexels のトップページ( https://www.pexels.com/ )へアクセスし、右上の「Sign Up」または「Log In」からアカウントを作成/ログインします。
- フッターにある Developers リンクをクリックし、開発者向けダッシュボードへ遷移します。
- ダッシュボード上部の Create New API Key ボタンを押すとモーダルが表示されます。アプリ名や利用目的(Web / Mobile / Other)を入力して Generate をクリックすると、キーが即座に生成されます。
重要ポイント
- 取得したキーは画面上で一度だけ表示されるため、必ずコピーして.envファイル等安全な場所に保存してください。
- キーの再発行や削除は同じダッシュボードから行えますが、変更後はすべてのリクエストで新しいキーを使用する必要があります。
無料プランの利用制限と商用利用条件
Pexels は無料プランでも実務レベルの利用が可能ですが、リクエスト数や商用利用に関するルールがあります。これらを正しく把握しておかないと、サービス停止やライセンス違反につながる恐れがあります。
無料プランの主な制限(2024 年 10 月時点)
| 項目 | 上限・条件 |
|---|---|
| 月間リクエスト数 | 最大 20,000 回 |
| 秒間リクエスト数 | 最大 5 回/秒 |
| 対象コンテンツ | 静止画・動画の両方 |
| 商用利用可否 | 可(再配布は不可) |
| クレジット表示 | 任意だが推奨 |
ポイント:商用プロダクトでの使用は許可されていますが、画像そのものを販売したり、素材として再配布することは禁じられています。クレジット表記は必須ではありませんが、Pexels のブランド保護の観点から「画像提供: Pexels」の記載を推奨します。
認証ヘッダーと主要エンドポイント
Pexels API への全リクエストは Bearer トークン方式 の認証ヘッダーが必須です。また、画像検索と動画検索でエンドポイントが分かれている点に留意してください。
認証ヘッダーの構成
|
1 2 |
Authorization: Bearer <YOUR_API_KEY> |
<YOUR_API_KEY>は取得したキーを環境変数等から読み込むことが推奨されます。ハードコーディングはセキュリティ上危険です。
主なエンドポイントとパラメータ
| エンドポイント | 用途 | 主なクエリパラメータ |
|---|---|---|
/v1/search |
静止画検索 | query(必須)・per_page(最大 80)・page・orientation・size・locale |
/videos/search |
動画検索 | query(必須)・per_page・page・min_width・min_height |
備考:公式ドキュメントでは、画像検索は最大 80 件/ページ、動画検索は同様に取得件数を制御できます。過剰な
per_page指定はエラーの原因になるため注意してください。
言語別実装サンプル
以下では、主要プログラミング言語ごとに 環境変数から API キーを取得 する方法を中心にコード例を示します。全ての例で process.env(Node.js 系)や os.getenv(Python 系)等を利用し、キーがソースコードに残らないよう配慮しています。
JavaScript (Fetch)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
// .env ファイルに PEXELS_API_KEY=xxxxxx を設定し、dotenv パッケージでロードしてください import 'dotenv/config'; const apiKey = process.env.PEXELS_API_KEY; // 環境変数から取得 async function searchPhotos(query) { const params = new URLSearchParams({ query, per_page: '10', }); const response = await fetch(`https://api.pexels.com/v1/search?${params}`, { headers: { Authorization: `Bearer ${apiKey}` }, }); if (!response.ok) throw new Error(`HTTP ${response.status}`); return await response.json(); } // 使用例 searchPhotos('mountain') .then(data => console.log(data.photos)) .catch(err => console.error(err)); |
JavaScript (Axios)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
import axios from 'axios'; import dotenv from 'dotenv'; dotenv.config(); const apiKey = process.env.PEXELS_API_KEY; export const fetchVideos = async (keyword) => { try { const { data } = await axios.get('https://api.pexels.com/videos/search', { headers: { Authorization: `Bearer ${apiKey}` }, params: { query: keyword, per_page: 5 }, }); return data.videos; } catch (e) { console.error(e.response?.status, e.message); throw e; } }; |
Python (requests)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import os import requests API_KEY = os.getenv('PEXELS_API_KEY') # .env から読み込むことを想定 def search_photos(keyword: str, per_page: int = 12): url = 'https://api.pexels.com/v1/search' headers = {'Authorization': f'Bearer {API_KEY}'} params = {'query': keyword, 'per_page': per_page} resp = requests.get(url, headers=headers, params=params) resp.raise_for_status() # ステータスコードが 200 系でないと例外 return resp.json()['photos'] if __name__ == '__main__': photos = search_photos('sunset') for p in photos: print(p['src']['medium']) |
PHP (Guzzle)
|
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 |
<?php require 'vendor/autoload.php'; use GuzzleHttp\Client; use GuzzleHttp\Exception\GuzzleException; // .env から取得(vlucas/phpdotenv 推奨) $apiKey = getenv('PEXELS_API_KEY'); $client = new Client([ 'base_uri' => 'https://api.pexels.com/v1/', 'headers' => ['Authorization' => "Bearer {$apiKey}"] ]); try { $response = $client->request('GET', 'search', [ 'query' => [ 'query' => 'forest', 'per_page' => 8, ] ]); $data = json_decode($response->getBody(), true); foreach ($data['photos'] as $photo) { echo $photo['src']['medium'] . PHP_EOL; } } catch (GuzzleException $e) { error_log('Pexels API error: ' . $e->getMessage()); } |
Node.js(Express + Redis キャッシュ)
|
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 |
// server.js require('dotenv').config(); const express = require('express'); const axios = require('axios'); const { createClient } = require('redis'); const app = express(); const apiKey = process.env.PEXELS_API_KEY; const redisClient = createClient({ url: process.env.REDIS_URL }); (async () => { await redisClient.connect(); })(); app.get('/photos', async (req, res) => { const { q = 'city', per_page = 15 } = req.query; const cacheKey = `pexels:${q}:${per_page}`; // キャッシュ確認 const cached = await redisClient.get(cacheKey); if (cached) return res.json(JSON.parse(cached)); try { const { data } = await axios.get('https://api.pexels.com/v1/search', { headers: { Authorization: `Bearer ${apiKey}` }, params: { query: q, per_page }, }); // 15 分間キャッシュ await redisClient.setEx(cacheKey, 900, JSON.stringify(data)); res.json(data); } catch (err) { console.error(err); res.status(502).json({ error: 'Pexels API request failed' }); } }); app.listen(3000, () => console.log('Server listening on :3000')); |
共通注意点
- 各言語でprocess.env・os.getenv等からキーを取得し、コードベースに平文を書かないこと。
- CI/CD 環境でも同様に環境変数を設定し、漏洩リスクを最小化します。
エラーハンドリングとレートリミット対策
API 呼び出しが失敗した際の対応は、サービスの信頼性を保つ上で不可欠です。特に 429 Too Many Requests は頻発しやすく、適切なリトライロジックが求められます。
ステータスコード別対策(概要)
| HTTP ステータス | 主な原因 | 推奨対応 |
|---|---|---|
| 400 | パラメータ不正 | クエリを見直し、必須項目が抜けていないか確認 |
| 401 / 403 | 認証失敗・権限不足 | API キーとヘッダーの形式を再チェック |
| 429 | レートリミット超過 | Retry-After ヘッダーで待機し、指数バックオフで最大3回再試行 |
| 500 系 | サーバ障害 | 数秒待機後に再試行。継続失敗時はフォールバック処理を実装 |
JavaScript(Axios)でのリトライ実装例
|
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 |
import axios from 'axios'; import dotenv from 'dotenv'; dotenv.config(); const apiKey = process.env.PEXELS_API_KEY; async function getWithRetry(url, config, attempts = 3, backoff = 1000) { try { return await axios.get(url, { ...config }); } catch (err) { const status = err.response?.status; if (status === 429 && attempts > 0) { const retryAfter = parseInt(err.response.headers['retry-after'] || '1', 10); const delay = Math.max(retryAfter * 1000, backoff); await new Promise(r => setTimeout(r, delay)); return getWithRetry(url, config, attempts - 1, backoff * 2); } throw err; } } // 使用例 getWithRetry('https://api.pexels.com/v1/search', { headers: { Authorization: `Bearer ${apiKey}` }, params: { query: 'river' }, }) .then(res => console.log(res.data)) .catch(console.error); |
Python(requests)でのリトライ実装例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
import os, time, requests API_KEY = os.getenv('PEXELS_API_KEY') def get_json(url, params, retries=3, backoff=1): headers = {'Authorization': f'Bearer {API_KEY}'} while True: resp = requests.get(url, headers=headers, params=params) if resp.status_code == 429 and retries > 0: wait = int(resp.headers.get('Retry-After', '1')) time.sleep(max(wait, backoff)) retries -= 1 backoff *= 2 continue resp.raise_for_status() return resp.json() data = get_json( 'https://api.pexels.com/v1/search', {'query': 'forest', 'per_page': 10} ) print(data) |
ベストプラクティス
- リトライ回数は過度に増やさず、最大3回程度に抑える。
- バックオフ時間は指数的に伸ばすことで、サーバ側の負荷を緩和します。
- 429 が頻繁に返る場合は、リクエストレート自体を見直すか、キャッシュ導入を検討してください。
実装事例:React コンポーネント と WordPress プラグイン
React での画像ギャラリーコンポーネント
このコンポーネントは useEffect 内で非同期に Pexels API を呼び出し、取得した画像を レスポンシブなグリッド として表示します。環境変数からキーを取得し、AbortController でアンマウント時のリクエスト中止も実装しています。
|
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 |
import React, { useState, useEffect } from 'react'; type Photo = { id: number; src: { medium: string }; }; interface Props { query: string; } const PexelsGallery: React.FC<Props> = ({ query }) => { const [photos, setPhotos] = useState<Photo[]>([]); const [loading, setLoading] = useState(true); const [error, setError] = useState<string | null>(null); // API 呼び出しロジック(環境変数使用) useEffect(() => { const controller = new AbortController(); const fetchPhotos = async () => { try { const res = await fetch( `https://api.pexels.com/v1/search?query=${encodeURIComponent(query)}&per_page=12`, { headers: { Authorization: `Bearer ${process.env.REACT_APP_PEXELS_KEY}` }, signal: controller.signal, } ); if (!res.ok) throw new Error(`HTTP ${res.status}`); const data = await res.json(); setPhotos(data.photos); } catch (e: any) { if (e.name !== 'AbortError') setError(e.message); } finally { setLoading(false); } }; fetchPhotos(); return () => controller.abort(); // クリーンアップ }, [query]); if (loading) return <p>画像を読み込み中…</p>; if (error) return <p>エラー: {error}</p>; return ( <div className="grid gap-4 grid-cols-3"> {photos.map(p => ( <img key={p.id} src={p.src.medium} alt="" loading="lazy" /> ))} </div> ); }; export default PexelsGallery; |
ポイントまとめ
process.env.REACT_APP_PEXELS_KEYに API キーを格納し、.envを.gitignoreに入れる。AbortControllerが不要なネットワークトラフィックとメモリリークを防止。loading="lazy"でブラウザ側の遅延読み込みを有効化。
WordPress 用プラグイン(カスタム実装例)
WordPress の管理画面から「Pexels 画像インポート」ボタンを押すと、検索キーワードに合致した画像を メディアライブラリへ直接保存 できるシンプルなプラグインです。公式プラグイン名は存在しないため、以下は独自実装のサンプルコードとなります。
|
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 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
<?php /** * Plugin Name: Pexels Image Importer * Description: 管理画面からキーワード検索で取得した画像をメディアライブラリに保存します。 * Version: 1.0 * Author: Your Name */ if ( ! defined( 'ABSPATH' ) ) exit; // 環境変数から API キー取得(WP_ENV の .env ローダー等が前提) $pexels_api_key = getenv( 'PEXELS_API_KEY' ); add_action( 'admin_menu', function() { add_media_page( 'Pexels 画像インポート', 'Pexels インポート', 'upload_files', 'pexels-import', 'pexels_import_page' ); }); function pexels_import_page() { ?> <div class="wrap"> <h1>Pexels から画像をインポート</h1> <form method="post" action="<?php echo admin_url( 'admin-post.php' ); ?>"> <?php wp_nonce_field( 'pexels_import_action', 'pexels_nonce' ); ?> <input type="hidden" name="action" value="import_pexels_image"> <p> <label>検索キーワード: <input type="text" name="search_query" required></label> </p> <?php submit_button( 'インポート実行' ); ?> </form> </div> <?php } // ハンドラ:画像取得 → メディア登録 add_action( 'admin_post_import_pexels_image', function() { if ( ! current_user_can( 'upload_files' ) || ! check_admin_referer( 'pexels_import_action', 'pexels_nonce' ) ) wp_die( '権限がありません' ); $query = sanitize_text_field( $_POST['search_query'] ?? '' ); if ( empty( $query ) ) wp_die( '検索キーワードを入力してください' ); $api_key = getenv( 'PEXELS_API_KEY' ); $url = "https://api.pexels.com/v1/search?query=" . rawurlencode( $query ) . "&per_page=1"; $response = wp_remote_get( $url, [ 'headers' => [ 'Authorization' => "Bearer {$api_key}" ], 'timeout' => 15, ] ); if ( is_wp_error( $response ) ) wp_die( 'API エラー: ' . $response->get_error_message() ); $body = json_decode( wp_remote_retrieve_body( $response ), true ); $photo = $body['photos'][0] ?? null; if ( ! $photo ) wp_die( '画像が見つかりません' ); // ダウンロードしてメディアライブラリへ登録 $image_url = $photo['src']['original']; $tmp_file = download_url( $image_url ); if ( is_wp_error( $tmp_file ) ) wp_die( 'ダウンロード失敗: ' . $tmp_file->get_error_message() ); $file_array = [ 'name' => basename( $image_url ), 'tmp_name' => $tmp_file, ]; $attach_id = media_handle_sideload( $file_array, 0 ); if ( is_wp_error( $attach_id ) ) { @unlink( $tmp_file ); wp_die( 'メディア登録失敗: ' . $attach_id->get_error_message() ); } // 成功メッセージ wp_redirect( admin_url( 'upload.php?message=1' ) ); exit; }); |
実装のポイント
- 環境変数利用:
getenv('PEXELS_API_KEY')でキーを取得し、コードに埋め込んでいません。 wp_remote_getに認証ヘッダーを付与し、安全な API 呼び出しを実現。- ダウンロードした一時ファイルは
media_handle_sideloadでメディアライブラリへ登録し、不要になったら必ず削除しています。 - エラーハンドリングは WordPress の管理画面に通知できるよう
wp_dieとリダイレクトを組み合わせています。
まとめ
- API キー取得は公式 Developers ページから数クリックで完了し、取得後は環境変数へ保存してコードに直接書かない。
- 無料プランは月 20,000 リクエスト・秒間 5 回の上限があり、商用利用は可能(再配布禁止)。クレジット表記は任意だが推奨。
- 認証方式は
Bearerヘッダー必須で、画像検索と動画検索はエンドポイントが別々に提供されている。 - 実装例では全言語共通で環境変数からキーを取得し、ハードコーディングを排除した安全なサンプルコードを掲載。
- エラーハンドリングはステータスコード別に対策を分け、特に 429 の場合は
Retry-Afterに従い指数バックオフでリトライする。 - 実装事例として、React コンポーネントと WordPress 用カスタムプラグインのサンプルを提示し、環境変数・AbortController・WP のメディアハンドリングなどベストプラクティスを示した。
これらの手順とコードスニペットを参考にすれば、2024 年末時点で公開されている最新の Pexels API を 安全かつ効率的 にプロジェクトへ組み込むことができます。ぜひご自身の開発フローに合わせてカスタマイズし、実際に動作させてみてください。