Free Pricing API tutorial

How to Look Up CS2 Skin Prices

Build a small webpage that shows the price reported by each marketplace and when each price was checked.

Last updated 2026-09-04 · Reviewed by OpenSkin · 20 minutes · Beginner

What you will build

Build a small webpage where someone enters the full item name shown on Steam and sees the current price from each available marketplace.

Completed CS2 price lookup page showing marketplace prices and checked times
The finished page shows where each price came from and when it was checked.

Before you start

  • Python 3 to serve the files locally
  • A modern web browser
  • The full item name shown on the Steam Community Market

Project files

current-price-card/
  index.html
  styles.css
  app.js

Build it

  1. Create the form and results table

    The form asks for the full Steam market name. The results table stays hidden until the API returns a price.

  2. Request the item

    URLSearchParams correctly handles spaces, the pipe character, and the exterior in names such as AK-47 | Redline (Field-Tested).

  3. Create one row per marketplace

    Keep the marketplace name beside its price and checked time. Skip marketplaces that did not return a price.

  4. Show API errors

    Check the HTTP status before displaying results. An invalid or unknown item should show a message instead of a blank table.

  5. Serve and open the page

    Start the local server with the command below, then open http://localhost:8090 in a browser.

index.html

Form and result table

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>CS2 price lookup</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <main>
    <p class="eyebrow">Marketplace prices</p>
    <h1>CS2 price lookup</h1>
    <form id="lookup">
      <label for="item">Exact Steam market name</label>
      <div class="controls">
        <input id="item" value="AK-47 | Redline (Field-Tested)" required>
        <button>Get prices</button>
      </div>
    </form>
    <p id="status" role="status"></p>
    <section id="result" hidden>
      <h2 id="result-title"></h2>
      <table>
        <thead><tr><th>Marketplace</th><th>Listed price</th><th>Checked</th></tr></thead>
        <tbody id="prices"></tbody>
      </table>
    </section>
  </main>
  <script type="module" src="app.js"></script>
</body>
</html>

app.js

API request, error handling, and rendering

const API = 'https://api.openskin.dev/v1/prices'
const form = document.querySelector('#lookup')
const itemInput = document.querySelector('#item')
const status = document.querySelector('#status')
const result = document.querySelector('#result')
const title = document.querySelector('#result-title')
const tbody = document.querySelector('#prices')

const marketplaceNames = {steam:'Steam', skinport:'Skinport', buff:'Buff163', youpin:'YouPin', csfloat:'CSFloat'}
function marketplaceRows(payload) {
  return Object.entries(payload.prices ?? {})
    .flatMap(([marketplace, quote]) => {
      const ask = quote?.ask ?? null
      if (typeof ask !== 'number') return []
      return [{marketplace: marketplaceNames[marketplace] ?? marketplace, ask, observedAt: quote.updated_at ?? 'Not provided'}]
    })
    .sort((a, b) => a.ask - b.ask)
}

function addCell(row, value) {
  const cell = document.createElement('td')
  cell.textContent = value
  row.append(cell)
}

form.addEventListener('submit', async event => {
  event.preventDefault()
  result.hidden = true
  status.textContent = 'Looking up prices…'
  const query = new URLSearchParams({item: itemInput.value.trim()})
  try {
    const response = await fetch(`${API}?${query}`)
    const payload = await response.json()
    if (!response.ok) throw new Error(payload.error?.message ?? payload.message ?? `Request failed (${response.status})`)
    const rows = marketplaceRows(payload)
    if (!rows.length) throw new Error('No current prices are available for this item.')
    tbody.replaceChildren()
    for (const price of rows) {
      const row = document.createElement('tr')
      addCell(row, price.marketplace)
      addCell(row, new Intl.NumberFormat('en-US', {style:'currency', currency:'USD'}).format(price.ask))
      addCell(row, price.observedAt === 'Not provided' ? price.observedAt : new Date(price.observedAt).toLocaleString())
      tbody.append(row)
    }
    title.textContent = payload.item ?? itemInput.value.trim()
    status.textContent = `${rows.length} marketplaces returned`
    result.hidden = false
  } catch (error) {
    status.textContent = error instanceof Error ? error.message : 'The request failed.'
  }
})

styles.css

Readable responsive layout

:root { color-scheme: dark; font-family: system-ui, sans-serif; background:#141614; color:#f3f4f3; }
body { margin:0; padding:48px 20px; }
main { width:min(760px,100%); margin:auto; }
.eyebrow { color:#8eb69a; font:600 12px ui-monospace,monospace; text-transform:uppercase; }
h1 { margin:8px 0 32px; font-size:clamp(36px,8vw,64px); letter-spacing:-.04em; }
label { display:block; margin-bottom:8px; color:#b7bbb8; }
.controls { display:flex; gap:10px; }
input,button { min-height:44px; border:1px solid #3b403c; border-radius:6px; font:inherit; }
input { flex:1; min-width:0; padding:0 12px; background:#1d201e; color:inherit; }
button { padding:0 18px; background:#376f49; color:white; cursor:pointer; }
#status { min-height:24px; color:#aeb2af; }
section { margin-top:28px; border-top:1px solid #343735; }
table { width:100%; border-collapse:collapse; }
th,td { padding:13px 8px; border-bottom:1px solid #303331; text-align:left; }
th { color:#9ea29f; font-size:12px; }
td:nth-child(2) { font-variant-numeric:tabular-nums; }
@media (max-width:560px) { .controls { display:grid; } th:nth-child(3),td:nth-child(3) { font-size:11px; } }

Run it

cd current-price-card
python3 -m http.server 8090

Open http://localhost:8090 in your browser.

Expected output

AK-47 | Redline (Field-Tested)

Marketplace   Listed price   Checked
CSFloat       $21.91         Sep 4, 2026, 5:13 AM
Steam         $24.38         Sep 4, 2026, 5:12 AM

How it works

  • The full item name shown on Steam includes the exterior. AK-47 | Redline and AK-47 | Redline (Field-Tested) are different items.
  • The page sorts prices from lowest to highest but keeps each marketplace separate.
  • If a marketplace has no price, the page leaves it out. It does not turn missing data into a $0 price.

Verify the result

Enter the full item name shown on Steam and confirm that the table shows at least one marketplace, price, and checked time. An unknown item should show an error instead of an empty or zero price.

Troubleshooting

What you seeLikely causeWhat to do
400 Invalid itemThe item parameter is empty or malformed.Copy the full item name shown on Steam, including the exterior.
404 Unknown itemThe catalog does not contain that exact market name.Check spelling and punctuation against Steam or the OpenSkin catalog.
Table is emptyKnown item, but no marketplace currently has an ask.Show “No current asks” and keep the value missing rather than using zero.