無料で使えるAPI(2025年版)

windows JavaScript
スポンサーリンク

汎用APIを実際に使うHTML+JSデモ

See the Pen Free API Demos (Weather, News, Translation, Currency, Images, Maps) by MONO365 -Color your days- (@monoqlo365) on CodePen.

<!doctype html>
<html lang="ja">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1" />
  <title>汎用APIデモ — Weather / News / Translate / FX / Images / Holidays</title>
  <style>
    body{font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial;s}
    header{display:flex;gap:12px;align-items:center;padding:12px;background:#0f172a;color:#fff}
    .container{max-width:980px;margin:18px auto;padding:12px}
    nav button{margin-right:8px}
    section{display:none;padding:12px;border:1px solid #e5e7eb;border-radius:8px;background:#fff}
    section.active{display:block}
    .row{display:flex;gap:12px;align-items:flex-start}
    .card{flex:1;padding:12px;border:1px dashed #e5e7eb;border-radius:8px}
    pre{white-space:pre-wrap;background:#f8fafc;padding:8px;border-radius:6px;overflow:auto}
    input,select,textarea{width:100%;padding:8px;margin:6px 0;border:1px solid #cbd5e1;border-radius:6px}
    button.primary{background:#06b6d4;border:none;color:#fff;padding:8px 12px;border-radius:6px;cursor:pointer}
    .thumb{width:120px;height:80px;object-fit:cover;border-radius:6px}
    .small{font-size:13px;color:#374151}
  </style>
</head>
<body>
<header>
  <h1 style="margin:0;font-size:18px">汎用API 実演デモ</h1>
  <div class="small">OpenWeatherMap / NewsAPI / LibreTranslate / ExchangeRate.host / Pixabay / Nager.Date をデモ</div>
</header>
<div class="container">
  <nav>
    <button data-target="weather">天気</button>
    <button data-target="news">ニュース</button>
    <button data-target="translate">翻訳</button>
    <button data-target="fx">為替</button>
    <button data-target="images">画像検索</button>
    <button data-target="holidays">祝日</button>
  </nav>

  <!-- 天気 -->
  <section id="weather">
    <h2>天気デモ</h2>
    <div class="row">
      <div class="card">
        <label>都市名(例: Tokyo)</label>
        <input id="weather-city" placeholder="Tokyo" />
        <label>OpenWeatherMap APIキー(任意)</label>
        <input id="owm-key" placeholder="APIキーを貼り付け" />
        <div style="margin-top:6px">
          <button class="primary" id="btn-weather">取得</button>
        </div>
        <p class="small">※ OpenWeatherMap APIキーを入れない場合、デモ用の簡易データ(ダミー)を表示します。</p>
      </div>
      <div class="card" id="weather-result">
        <h3>結果</h3>
        <div id="weather-output">ここに結果が出ます</div>
        <pre id="weather-json"></pre>
      </div>
    </div>
  </section>

  <!-- ニュース -->
  <section id="news">
    <h2>ニュースデモ</h2>
    <div class="row">
      <div class="card">
        <label>国コード(例: jp)</label>
        <input id="news-country" placeholder="jp" />
        <label>NewsAPI.org APIキー(必要)</label>
        <input id="news-key" placeholder="APIキーを貼り付け" />
        <button class="primary" id="btn-news">取得</button>
        <p class="small">※ NewsAPI はブラウザから直接呼ぶとCORSでブロックされる場合があります。問題が出たらプロキシ経由で試してください。</p>
      </div>
      <div class="card" id="news-result">
        <h3>見出し</h3>
        <ul id="news-list"></ul>
        <pre id="news-json"></pre>
      </div>
    </div>
  </section>

  <!-- 翻訳 -->
  <section id="translate">
    <h2>翻訳デモ(LibreTranslate)</h2>
    <div class="row">
      <div class="card">
        <label>翻訳したいテキスト</label>
        <textarea id="txt-src" rows="4">Hello, how are you?</textarea>
        <label>ソース言語(auto可)</label>
        <input id="src-lang" placeholder="auto" value="auto" />
        <label>ターゲット言語(例: ja)</label>
        <input id="tgt-lang" placeholder="ja" value="ja" />
        <button class="primary" id="btn-translate">翻訳</button>
      </div>
      <div class="card">
        <h3>翻訳結果</h3>
        <div id="translate-output"></div>
        <pre id="translate-json"></pre>
      </div>
    </div>
  </section>

  <!-- 為替 -->
  <section id="fx">
    <h2>為替デモ(ExchangeRate.host)</h2>
    <div class="row">
      <div class="card">
        <label>基準通貨(例: USD)</label>
        <input id="fx-base" value="USD" />
        <label>変換先(カンマ区切りで複数。例: JPY,EUR)</label>
        <input id="fx-symbols" value="JPY" />
        <button class="primary" id="btn-fx">取得</button>
      </div>
      <div class="card">
        <h3>為替レート</h3>
        <div id="fx-output"></div>
        <pre id="fx-json"></pre>
      </div>
    </div>
  </section>

  <!-- 画像検索 -->
  <section id="images">
    <h2>画像検索デモ(Pixabay)</h2>
    <div class="row">
      <div class="card">
        <label>検索ワード</label>
        <input id="img-query" value="cat" />
        <label>Pixabay APIキー(必要)</label>
        <input id="pixabay-key" placeholder="APIキーを貼り付け" />
        <button class="primary" id="btn-images">検索</button>
        <p class="small">※ APIキーが無い場合はダミー画像を表示します。</p>
      </div>
      <div class="card">
        <h3>検索結果</h3>
        <div id="images-output" style="display:flex;flex-wrap:wrap;gap:8px"></div>
        <pre id="images-json"></pre>
      </div>
    </div>
  </section>

  <!-- 祝日 -->
  <section id="holidays">
    <h2>祝日デモ(Nager.Date)</h2>
    <div class="row">
      <div class="card">
        <label>年(例: 2025)</label>
        <input id="year" value="2025" />
        <label>国コード(例: JP)</label>
        <input id="country" value="JP" />
        <button class="primary" id="btn-holidays">取得</button>
      </div>
      <div class="card">
        <h3>祝日一覧</h3>
        <ul id="holidays-list"></ul>
        <pre id="holidays-json"></pre>
      </div>
    </div>
  </section>

</div>
<script>
// シンプルなタブ
document.querySelectorAll('nav button').forEach(b=>{
  b.addEventListener('click',()=>{
    document.querySelectorAll('section').forEach(s=>s.classList.remove('active'));
    document.getElementById(b.dataset.target).classList.add('active');
  });
});
// 初期タブ
document.querySelector('nav button').click();

// --- 天気 ---
document.getElementById('btn-weather').addEventListener('click',async ()=>{
  const city = document.getElementById('weather-city').value || 'Tokyo';
  const key = document.getElementById('owm-key').value.trim();
  const out = document.getElementById('weather-output');
  const js = document.getElementById('weather-json');
  out.innerHTML='取得中...'; js.textContent='';
  try{
    if(key){
      const url = `https://api.openweathermap.org/data/2.5/weather?q=${encodeURIComponent(city)}&appid=${encodeURIComponent(key)}&lang=ja&units=metric`;
      const r = await fetch(url);
      if(!r.ok) throw new Error('OpenWeatherMapからエラー: '+r.status);
      const j = await r.json();
      out.innerHTML = `<strong>${j.name}</strong> — ${j.weather?.[0]?.description || ''}<br>気温: ${j.main?.temp} ℃`;
      js.textContent = JSON.stringify(j,null,2);
    } else {
      // ダミー表示(キー無しデモ)
      const sample = {name: city, weather:[{description:'晴れ'}], main:{temp:23.4}};
      out.innerHTML = `<strong>${sample.name}</strong> — ${sample.weather[0].description}<br>気温: ${sample.main.temp} ℃ (ダミー)`;
      js.textContent = JSON.stringify(sample,null,2);
    }
  }catch(e){ out.innerHTML = 'エラー: '+e.message; js.textContent=''; }
});

// --- ニュース ---
document.getElementById('btn-news').addEventListener('click',async ()=>{
  const country = document.getElementById('news-country').value || 'jp';
  const key = document.getElementById('news-key').value.trim();
  const list = document.getElementById('news-list');
  const js = document.getElementById('news-json');
  list.innerHTML='取得中...'; js.textContent='';
  try{
    if(!key){ list.innerHTML='<li>APIキーが必要です(NewsAPI.org)。</li>'; return; }
    const url = `https://newsapi.org/v2/top-headlines?country=${encodeURIComponent(country)}&apiKey=${encodeURIComponent(key)}`;
    const r = await fetch(url);
    if(!r.ok) throw new Error('NewsAPIエラー: '+r.status+' (CORS制限の可能性あり)');
    const j = await r.json();
    js.textContent = JSON.stringify(j,null,2);
    list.innerHTML = '';
    (j.articles||[]).slice(0,10).forEach(a=>{
      const li = document.createElement('li');
      li.innerHTML = `<a href="${a.url}" target="_blank">${a.title}</a> <span class="small">${a.source?.name||''}</span>`;
      list.appendChild(li);
    });
    if((j.articles||[]).length===0) list.innerHTML='<li>見つかりませんでした</li>';
  }catch(e){ list.innerHTML = '<li>エラー: '+e.message+'</li>'; js.textContent=''; }
});

// --- 翻訳 (LibreTranslate) ---
document.getElementById('btn-translate').addEventListener('click',async ()=>{
  const q = document.getElementById('txt-src').value;
  const src = document.getElementById('src-lang').value || 'auto';
  const tgt = document.getElementById('tgt-lang').value || 'ja';
  const out = document.getElementById('translate-output');
  const js = document.getElementById('translate-json');
  out.innerHTML='翻訳中...'; js.textContent='';
  try{
    const url = 'https://libretranslate.com/translate';
    const r = await fetch(url,{
      method:'POST',
      headers:{'Content-Type':'application/json'},
      body: JSON.stringify({q,source:src,target:tgt,format:'text'})
    });
    if(!r.ok) throw new Error('LibreTranslateエラー: '+r.status);
    const j = await r.json();
    out.textContent = j.translatedText;
    js.textContent = JSON.stringify(j,null,2);
  }catch(e){ out.innerHTML='エラー: '+e.message; js.textContent=''; }
});

// --- 為替 ---
document.getElementById('btn-fx').addEventListener('click',async ()=>{
  const base = document.getElementById('fx-base').value || 'USD';
  const symbols = document.getElementById('fx-symbols').value || 'JPY';
  const out = document.getElementById('fx-output');
  const js = document.getElementById('fx-json');
  out.innerHTML='取得中...'; js.textContent='';
  try{
    const url = `https://api.exchangerate.host/latest?base=${encodeURIComponent(base)}&symbols=${encodeURIComponent(symbols)}`;
    const r = await fetch(url);
    if(!r.ok) throw new Error('ExchangeRate.hostエラー: '+r.status);
    const j = await r.json();
    js.textContent = JSON.stringify(j,null,2);
    out.innerHTML = Object.entries(j.rates||{}).map(([k,v])=>`<div><strong>${k}</strong>: ${v}</div>`).join('');
  }catch(e){ out.innerHTML='エラー: '+e.message; js.textContent=''; }
});

// --- 画像検索 (Pixabay) ---
document.getElementById('btn-images').addEventListener('click',async ()=>{
  const q = document.getElementById('img-query').value || 'cat';
  const key = document.getElementById('pixabay-key').value.trim();
  const out = document.getElementById('images-output');
  const js = document.getElementById('images-json');
  out.innerHTML='取得中...'; js.textContent='';
  try{
    if(!key){
      // ダミー画像(外部ホスト)
      out.innerHTML = Array.from({length:6}).map((_,i)=>`<div><img class="thumb" src="https://placekitten.com/200/${150+i}" alt="kitten"></div>`).join('');
      js.textContent = '{"note":"APIキーが無いためダミー画像を表示しています"}';
      return;
    }
    const url = `https://pixabay.com/api/?key=${encodeURIComponent(key)}&q=${encodeURIComponent(q)}&per_page=12&image_type=photo&lang=ja`;
    const r = await fetch(url);
    if(!r.ok) throw new Error('Pixabayエラー: '+r.status);
    const j = await r.json();
    js.textContent = JSON.stringify(j,null,2);
    out.innerHTML = (j.hits||[]).map(h=>`<div><a href="${h.pageURL}" target="_blank"><img class="thumb" src="${h.previewURL}" alt="${h.tags}"></a></div>`).join('');
    if((j.hits||[]).length===0) out.innerHTML='<div>見つかりませんでした</div>';
  }catch(e){ out.innerHTML='エラー: '+e.message; js.textContent=''; }
});

// --- 祝日 ---
document.getElementById('btn-holidays').addEventListener('click',async ()=>{
  const year = document.getElementById('year').value || '2025';
  const country = document.getElementById('country').value || 'JP';
  const list = document.getElementById('holidays-list');
  const js = document.getElementById('holidays-json');
  list.innerHTML='取得中...'; js.textContent='';
  try{
    const url = `https://date.nager.at/api/v3/PublicHolidays/${encodeURIComponent(year)}/${encodeURIComponent(country)}`;
    const r = await fetch(url);
    if(!r.ok) throw new Error('Nager.Dateエラー: '+r.status);
    const j = await r.json();
    js.textContent = JSON.stringify(j,null,2);
    list.innerHTML = (j||[]).map(h=>`<li>${h.date}${h.localName} (${h.name})</li>`).join('');
  }catch(e){ list.innerHTML='エラー: '+e.message; js.textContent=''; }
});
</script>
</body>
</html>
HTML

ポイント:

  • OpenWeatherMap, NewsAPI, Pixabay は APIキー入力欄 を用意(無ければダミー表示や注意文を出します)。
  • LibreTranslate / ExchangeRate.host / Nager.Date / REST系は APIキー不要 で即試せます。
  • NewsAPI はブラウザから直接呼ぶと CORS 制限が出る場合がある旨の注記あり。
  • 初心者向けに最小限の UI と取得結果の JSON 表示を用意しました。

See the Pen General-Purpose API + Map Demo by MONO365 -Color your days- (@monoqlo365) on CodePen.

タイトルとURLをコピーしました