A small, polished dashboard for viewing a Clash of Clans player's recent battle log, using the official Clash of Clans API.
- ✅ Look up any player tag and show their recent battles: opponent, battle type, stars, destruction %, trophy change, and rough time.
coc-dashboard/
├── server/ # Express backend — keeps your API token secret
│ ├── server.js
│ ├── package.json
│ └── .env.example
└── public/ # Static frontend, served by the backend
├── index.html
├── css/style.css
└── js/app.js
The frontend never sees your API token. It calls your backend
(/api/players/:tag/battlelog), and the backend attaches the token
server-side when it calls Clash of Clans.
- Go to https://developer.clashofclans.com and sign in.
- Under My Account, create a new key.
- Important: the key must be whitelisted to the public IP address
of the machine that will run this backend. If you're running it on
your own laptop, use
https://api.ipify.org(or just Google "what's my IP") to find that address and enter it when creating the key. If your IP changes (e.g. you switch networks), you'll need to edit the key's allowed IP in the developer portal.
cd coc-dashboard/server
npm installcp .env.example .envOpen .env and paste your token:
COC_API_TOKEN=your_real_token_here
PORT=3001
npm startThen open http://localhost:3001 in your browser.
If your public IP changes often (common on home networks), set
COC_AUTO_TOKEN=true in .env along with COC_EMAIL / COC_PASSWORD
(your developer.clashofclans.com login). On startup — and automatically
on any 403 — the server detects your current IP and creates or reuses
an API key scoped to it, so you stop hitting IP-mismatch errors.
This uses developer.clashofclans.com's own internal API (the same
calls the website makes when you use it), not the public game API, so
it's unofficial and could break if Supercell changes their site. If it
stops working, fall back to manual mode (COC_API_TOKEN + COC_AUTO_TOKEN=false)
and generate a key by hand.
Keep .env out of version control either way — with auto mode enabled
it holds your actual account password, not just an API key.
The backend is organized so new endpoints are one small addition each:
- In
server/server.js, add a route, e.g.:app.get('/api/clans/:tag', async (req, res) => { try { const tag = normalizeTag(req.params.tag); const data = await callCoC(`/clans/${encodeURIComponent(tag)}`); res.json(data); } catch (err) { handleError(err, res); } });
- In
public/js/app.js, add a small render function and call it the same wayrenderBattlesis called.
Good next endpoints to try: /players/{tag} (profile, trophies, troop
levels), /clans/{tag} (clan info), /clans/{tag}/warlog (if public).
The battle log is public data tied to a tag — nothing here requires anyone's permission to look up. That said, if this dashboard is about a specific real person, it's worth thinking about whether they'd be comfortable knowing it exists, especially if it ever grows beyond battle stats into anything that feels like tracking someone's activity. Might be a nicer gift shown to her than kept secret from her.