gpu1.ai Snapshot · Oct 18, 2026 · 3:52 PM EDTOct 18 · 3:52 PM EDT

The cheapest GPU in the cloud, found for you.

gpu1.ai tracks live rental prices for the GPUs people actually train and serve models on — across Vast.ai's marketplace and RunPod — normalized per GPU, per hour, so an 8-GPU rig and a single card compare fairly.

13GPUs tracked
342Vast.ai offers sampled
2Providers compared
$0.12Cheapest GPU/hr
gpu1 — cheapest per GPU, USD/hr

Cheapest right now

The four GPUs people ask about most, at the snapshot below. Marketplace prices move constantly — the deploy guide further down wires this exact page to refresh itself hourly.

Full price comparison

Every price is per GPU per hour. Vast.ai figures come from live marketplace offers (cheapest and median); RunPod shows its current lowest available rate. “Best” is whichever provider wins that row — and that's where the Rent button points.

GPUVRAMVast.ai from Vast.ai medianRunPod from Best

Inside the marketplace

The actual cheapest Vast.ai machines behind the headline numbers, sorted by per-GPU price. Watch the trade-off the headline hides: the rock-bottom offer sometimes sits on a host with a lower reliability score — the table note gives each GPU's “reliable floor”, the cheapest offer from a host rated 98% or better.

$/GPU/hrTotal $/hrGPUs LocationReliabilityHost CPU RAMDiskDown / Up Mbps

What will your run cost?

Pick a workload — or dial in your own GPU, count, and hours — and see the bill on each provider at snapshot prices. Then check the rent-vs-buy line before you reach for a credit card.

Your run

The bill

Best case = the cheapest single offer at snapshot; it may be gone by the time you click. Typical = median of live offers — the safer planning number. Storage, egress, and your own time aren't included, because they're never included in anyone's headline price either.

The providers, honestly

Two very different animals. gpu1.ai links to both through affiliate programs — disclosed in plain sight, because a comparison site you can't trust is worth nothing.

Vast.ai

A marketplace of independent GPU hosts bidding for your job.

  • Cheapest headline prices anywhere — hosts compete, so a 4090 dips to about $0.38/GPU/hr and an H100 to $1.34.
  • Quality varies by host. Filter by the reliability score; the cheapest offer isn't always the one that finishes your training run.
  • Best for: batch jobs, fine-tuning, experiments — anything checkpointed that can survive a host hiccup.

How gpu1.ai earns: Vast.ai pays 3% of everything you spend, for the life of your account. Your price doesn't change — the cut comes out of their side.

Rent on Vast.ai

RunPod

A managed GPU cloud — Secure Cloud datacenters plus a Community Cloud.

  • Predictable availability. A fixed rate card instead of a bidding war; an H100 SXM is $2.69/hr at snapshot.
  • Per-second billing on pods, one-click templates, persistent volumes.
  • Best for: inference servers and long-running pods where “is it still up?” matters more than the last 20 cents.

How gpu1.ai earns: new accounts through this link get a $5–$500 credit bonus, and gpu1.ai earns credits too. A 12% cash affiliate tier unlocks after 25 paying referrals.

Get the RunPod credit bonus

On the roadmap: Lambda, CoreWeave, Vultr, and DigitalOcean rate cards join as curated rows next. Fixed-price clouds don't expose live-offer APIs the way a marketplace does, so their published rates get verified by hand before they enter the table.

How this site makes money

No ads-first nonsense, no selling data. One engine: affiliate revenue from people who were going to rent a GPU anyway and found a cheaper one here.

# Illustrative — assumptions stated, not a promise
100 active referred users × $1,000/mo GPU spend = $100,000/mo flowing through the links
× 3% lifetime affiliate cut (Vast.ai) → $3,000/mo, recurring
# Referrals stack: every month's new users add to every previous month's base.
# Later layers: sponsored placements (month 6+), a pricing-data API (year 2).

Host & deploy it: the full runbook

This page is the entire site — one static HTML file. In production it reads a prices.json file that a GitHub Action refreshes hourly from the two provider APIs; every refresh commits, and every commit auto-deploys on Cloudflare Pages. Total running cost: $0. Here is the exact path from this preview to gpu1.ai live.

GitHub repobubeamos/gpu1.ai — index.html, scripts/, prices.json
→
GitHub Actions cronHourly: fetch_prices.py pulls both APIs, commits prices.json
→
Cloudflare PagesAuto-deploys every push to main — no build step
→
gpu1.aiCustom domain on Pages, HTTPS by default

Create the repo and add the files

Create a public repo named gpu1.ai under your GitHub account (same flow as mtls.ai — and make sure the “Meta Muse AI” GitHub App has this repo selected, the way you fixed it last time). The repo holds exactly four things:

  • index.html — this page. In the production copy the prices load from prices.json (step 3); everything else is identical.
  • scripts/fetch_prices.py — the fetcher in step 2.
  • .github/workflows/prices.yml — the hourly cron in step 2.
  • prices.json — generated by the script; you commit the first one by hand.
terminal
gh repo create gpu1.ai --public --clone
cd gpu1.ai
mkdir -p scripts .github/workflows
# drop index.html in the root, and the two files from step 2 in place
python3 scripts/fetch_prices.py        # writes the first prices.json
git add -A && git commit -m "gpu1.ai v1: comparison table + price fetcher"
git push

Add the price fetcher and the hourly Action

Both APIs are public and need no keys. This is the production form of the spike script, extended with RunPod and per-GPU normalization — an 8×H100 rig's sticker price is divided by 8 so rows compare fairly. Two gotchas from the spike are baked in: Vast.ai's gpu_name uses spaces (“RTX 4090”, not RTX_4090), and extra query params like limit make its API return 400, so the plain query is the reliable form.

scripts/fetch_prices.py
#!/usr/bin/env python3
"""gpu1.ai price fetcher — writes prices.json next to index.html.
Sources (both public, no auth):
  Vast.ai  GET  cloud.vast.ai/api/v0/bundles/?q=<json>   (gpu_name uses SPACES)
  RunPod   POST api.runpod.io/graphql                     (gpuTypes.lowestPrice)
All prices normalized to USD per GPU per hour."""
import json, statistics, urllib.request, urllib.parse
from datetime import datetime, timezone

VAST = "https://cloud.vast.ai/api/v0/bundles/"
HEAD = {"User-Agent": "gpu1.ai/1.0"}
GPUS = ["B200", "H200", "H100 SXM", "RTX 5090", "RTX 4090", "RTX 3090",
        "RTX 3090 Ti", "L40S", "RTX A6000", "A40", "L4"]
VRAM = {"B200": 180, "H200": 141, "H100 SXM": 80, "RTX 5090": 32, "RTX 4090": 24,
        "RTX 3090": 24, "RTX 3090 Ti": 24, "L40S": 48, "RTX A6000": 48, "A40": 48, "L4": 24}
RUNPOD_NAME = {"H200": "H200 SXM", "A100 80GB": "A100 SXM", "A100 40GB": "A100 SXM 40GB"}

def vast_offers(name):
    q = {"gpu_name": {"eq": name}, "rentable": {"eq": True}, "rented": {"eq": False}}
    url = VAST + "?" + urllib.parse.urlencode({"q": json.dumps(q)})  # q only — extra params 400
    with urllib.request.urlopen(urllib.request.Request(url, headers=HEAD), timeout=40) as r:
        return json.load(r).get("offers", [])

def vast_row(offers):
    per = sorted(o["dph_total"] / max(o.get("num_gpus", 1), 1) for o in offers if o.get("dph_total"))
    if not per:
        return None
    best = min(offers, key=lambda o: o["dph_total"] / max(o.get("num_gpus", 1), 1))
    rel = [o for o in offers if (o.get("reliability2") or 0) >= 0.98]
    return {"min": round(per[0], 3), "median": round(statistics.median(per), 3),
            "offers": len(offers), "loc": best.get("geolocation"),
            "reliableMin": round(min(o["dph_total"] / max(o.get("num_gpus", 1), 1) for o in rel), 3) if rel else None}

def runpod_lowest():
    body = json.dumps({"operationName": "GpuTypes", "query":
        "query GpuTypes { gpuTypes { displayName lowestPrice(input:{gpuCount:1}) { uninterruptablePrice } } }"}).encode()
    req = urllib.request.Request("https://api.runpod.io/graphql", data=body,
        headers={**HEAD, "Content-Type": "application/json", "apollo-require-preflight": "true"})
    with urllib.request.urlopen(req, timeout=40) as r:
        types = json.load(r)["data"]["gpuTypes"]
    return {t["displayName"]: (t.get("lowestPrice") or {}).get("uninterruptablePrice") for t in types}

def main():
    rp = runpod_lowest()
    rows = []
    for name in GPUS:
        v = vast_row(vast_offers(name))
        if v:
            rows.append({"gpu": name, "vram": VRAM[name], "vast": v,
                         "runpod": rp.get(RUNPOD_NAME.get(name, name))})
    for disp, vram in [("A100 80GB", 80), ("A100 40GB", 40)]:  # one API name, two cards — split by VRAM
        offers = [o for o in vast_offers("A100 SXM4")
                  if abs(round((o.get("gpu_ram") or 0) / 1024) - vram) <= 4]
        v = vast_row(offers)
        if v:
            rows.append({"gpu": disp, "vram": vram, "vast": v, "runpod": rp.get(RUNPOD_NAME[disp])})
    out = {"fetchedAt": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"), "rows": rows}
    with open("prices.json", "w") as f:
        json.dump(out, f, indent=1)
    print(f"prices.json: {len(rows)} GPUs at {out['fetchedAt']}")

if __name__ == "__main__":
    main()
.github/workflows/prices.yml
name: refresh-prices
on:
  schedule:
    - cron: "17 * * * *"        # hourly, off the :00 rush
  workflow_dispatch:            # refresh by hand from the Actions tab
permissions:
  contents: write               # the bot commits prices.json back to main
jobs:
  fetch:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - run: python3 scripts/fetch_prices.py
      - run: |
          git config user.name "gpu1-price-bot"
          git config user.email "bot@gpu1.ai"
          git add prices.json
          git diff --cached --quiet || git commit -m "prices: hourly refresh"
          git push

Wire index.html to prices.json

One change from this preview, which carries its snapshot inline: the production page fetches the JSON the Action keeps fresh, then renders the same tables. If the fetch fails, it falls back to the inline snapshot so the page never renders empty.

index.html — data wiring
// production: load the freshest committed snapshot, then render
fetch('prices.json')
  .then(r => r.json())
  .then(d => render(d.rows, d.fetchedAt))
  .catch(() => render(INLINE_SNAPSHOT.rows, INLINE_SNAPSHOT.fetchedAt));

Connect Cloudflare Pages

The same setup that worked for mtls.ai. In the Cloudflare dashboard: Workers & Pages → Create → Pages → Connect to Git, pick the gpu1.ai repo, then:

  • Project name: gpu1-ai (your preview URL becomes gpu1-ai.pages.dev)
  • Framework preset: None
  • Build command: leave empty — there is no build step
  • Build output directory: / (the repo root)
  • Hit Save and Deploy. From then on, every push to main — including the price bot's hourly commits — redeploys automatically in under a minute.

Attach the gpu1.ai domain

In the Pages project: Custom domains → Set up a custom domain → gpu1.ai. If the domain's DNS is already on Cloudflare, the record is created for you and HTTPS is automatic. You bought gpu1.ai at a registrar, so if its DNS isn't on Cloudflare yet, either point the domain's nameservers to Cloudflare first (free, and it's how mtls.ai is set up) or add the CNAME Pages gives you at your registrar — apex domains generally need Cloudflare DNS or CNAME flattening, so the nameserver route is the painless one. Then add www.gpu1.ai as a second custom domain and redirect it to the apex.

Verify the money plumbing

Before announcing anything, click every Rent button on the live site and confirm the URLs carry your codes — ref_id=751418 on Vast.ai (the dedicated, never-rented referral account, so earnings can cash out) and ref=aadmljc2 on RunPod. Check the Action ran green in the repo's Actions tab, and that gpu1.ai/prices.json shows a recent timestamp.

Launch checklist

  • Search Console: add gpu1.ai and submit the URL — the “cheapest H100” queries are the whole SEO game.
  • Announce it: a build-in-public X thread (live price drops are the hook), a @bube.builds carousel, and the link in both bios.
  • First deep-dive: publish “What it actually costs to fine-tune Llama 3 8B” using the calculator's numbers — that's the page other engineers link to.
  • Weekly price-drop post: the Action's commit history is a ready-made changelog; the biggest drop of the week becomes a recurring post and, later, the newsletter.
  • Milestone watch: at 25 paying RunPod referrals the 12% cash tier unlocks — that's the day RunPod stops being credit money.

Affiliate disclosure

The short version: links to Vast.ai and RunPod on this page are affiliate/referral links. If you rent a GPU through one, the provider pays gpu1.ai a cut — 3% of your spend on Vast.ai, for the life of your account; on RunPod, referral credits today and a 12% cash tier after 25 paying referrals. Your price is exactly the same as going direct — and on RunPod you get a $5–$500 credit bonus for coming through the link.

About the prices: every figure on this page was pulled from the providers' own public APIs (Vast.ai marketplace offers and RunPod's pricing endpoint) at the snapshot time shown — nothing is hand-typed and nothing is sponsored. Marketplace prices are live inventory: the cheapest offer can be rented by someone else a minute later, which is why the table shows medians alongside minimums. Sponsored placements, if they ever appear, will be labeled as such and will never change a price in the table.