Save every friend on your Steam account as a spreadsheet: name, online status, the game they are playing, SteamID64 and profile link. Free, in your own browser, with no Steam API key and without connecting your account to any site.
Sign in on steamcommunity.com and open your Friends page (Profile > Friends), then run the script. Works on anyone's friends list if it is public.
// Responsive Muse · Steam Friends List Exporter · v1.0 · 2026-11-12
// Saves a Steam friends list (yours, or anyone's whose friends list is public) to CSV or TXT:
// name, status, game being played, SteamID64 and profile link. Handy to back up your friends
// before a ban, an account move or a purge. Runs only on a steamcommunity.com profile's Friends
// page. It reads the list the page already shows: it makes no network requests of its own and
// never reads cookies, passwords or tokens.
(async () => {
const TOOL = 'Export Steam friends';
const FORMAT = 'csv'; // 'csv' (Excel, Sheets) or 'txt' ("Name - profile link", one per line)
const SORT = 'page'; // 'page' (as Steam shows them: in-game, online, offline) or 'name' (A to Z)
if (location.hostname !== 'steamcommunity.com' || !/^\/(id|profiles)\/[^/]+\/friends\/?$/.test(location.pathname)) {
alert('Open a Friends page first, for example your own:\nhttps://steamcommunity.com/my/friends/');
return;
}
// A small box on the page shows progress and asks before changing anything,
// so you never need to read or edit the console.
const many = (n, word) => `${n} ${word}${n === 1 ? '' : 's'}`; // 1 video, 2 videos
const panel = (() => {
const box = document.createElement('div');
box.style.cssText = 'display:block!important;position:fixed;right:16px;bottom:16px;z-index:2147483647;width:340px;max-width:calc(100vw - 32px);' +
'background:#111318;color:#e6e8ee;font:14px/1.5 system-ui,sans-serif;border-radius:12px;padding:16px;' +
'box-shadow:0 8px 30px rgba(0,0,0,.4);text-align:left';
const head = document.createElement('strong');
head.textContent = TOOL;
const msg = document.createElement('p');
msg.style.cssText = 'margin:8px 0 12px;white-space:pre-line';
const row = document.createElement('div');
row.style.cssText = 'display:flex;flex-wrap:wrap;gap:8px;justify-content:flex-end';
box.append(head, msg, row);
document.body.append(box);
const button = (label, primary, onClick) => {
const b = document.createElement('button');
b.textContent = label;
b.style.cssText = 'font:600 14px system-ui,sans-serif;padding:8px 14px;border-radius:8px;cursor:pointer;' +
(primary ? 'background:#0f766e;color:#fff;border:1px solid #0f766e' : 'background:none;color:#e6e8ee;border:1px solid #3a3f4b');
b.onclick = onClick;
row.append(b);
};
return {
text(t) { msg.textContent = t; },
ask(t, yes) {
msg.textContent = t;
row.replaceChildren();
return new Promise(r => {
button('Cancel', false, () => { row.replaceChildren(); r(false); });
button(yes, true, () => { row.replaceChildren(); r(true); });
});
},
stoppable(onStop) { row.replaceChildren(); button('Stop', false, onStop); },
actions(t, list) {
msg.textContent = t;
row.replaceChildren();
list.forEach(([label, primary, run]) => button(label, primary, run));
},
finish(t) { this.actions(t, [['Close', true, () => box.remove()]]); },
close() { box.remove(); },
};
})();
// Offer the result as a downloaded file or as clipboard text (a real click, so it always works)
const deliver = (summary, body, file) => {
const save = () => {
const a = document.createElement('a');
a.href = URL.createObjectURL(new Blob([/\.csv$/.test(file) ? '\ufeff' + body : body], { type: 'text/plain;charset=utf-8' }));
a.download = file;
a.click();
setTimeout(() => URL.revokeObjectURL(a.href), 5000);
panel.text(`${summary}\nSaved as ${file} (check your Downloads).`);
};
const copy = () => navigator.clipboard.writeText(body)
.then(() => panel.text(`${summary}\nCopied. Paste it into a spreadsheet or a note.`))
.catch(() => panel.text(`${summary}\nThe browser blocked the clipboard: use Download instead.`));
panel.actions(summary, [['Close', false, () => panel.close()], ['Copy', false, copy], ['Download', true, save]]);
};
// 1. Every friend is already on the page (Steam doesn't paginate this list)
const rows = [...document.querySelectorAll('.search_results [data-steamid]')];
if (!rows.length) {
panel.finish('No friends found. The friends list is private or empty. If you can see friends on the page, Steam may have changed its layout: please report it on responsive-muse.com.');
return 0;
}
// 2. One row per friend
const status = el => /\bin-game\b/.test(el.className) ? 'In game' : /\bonline\b/.test(el.className) ? 'Online' : 'Offline';
const list = rows.map((el, i) => {
const box = el.querySelector('.friend_block_content');
const small = box?.querySelector('.friend_small_text');
const game = small?.querySelector('.friend_game_link')?.textContent.trim() || '';
const nick = box?.querySelector('.nickname, .player_nickname_hint')?.textContent.trim() || '';
return {
order: i + 1,
name: (box?.firstChild?.textContent || '').trim() || el.dataset.steamid,
nick,
status: status(el),
game,
// signed in on your own list, Steam adds "Last Online 3 days ago" next to offline friends
detail: game ? '' : ((box?.querySelector('.friend_last_online_text') || small)?.textContent || '').replace(/\s+/g, ' ').trim(),
id: el.dataset.steamid,
url: (el.querySelector('a.selectable_overlay')?.href || `https://steamcommunity.com/profiles/${el.dataset.steamid}`).split('?')[0],
};
});
if (SORT === 'name') list.sort((x, y) => x.name.localeCompare(y.name, undefined, { sensitivity: 'base' }));
// 3. Build the file and offer it
const cell = v => '"' + String(v).replace(/"/g, '""') + '"';
const body = FORMAT === 'txt'
? list.map(f => `${f.name} - ${f.url}`).join('\n')
: ['Name,Nickname,Status,Playing,Last online,SteamID64,Profile URL', ...list.map(f =>
[f.name, f.nick, f.status, f.game, f.detail, f.id, f.url].map(cell).join(','))].join('\n');
const playing = list.filter(f => f.status === 'In game').length;
const online = list.filter(f => f.status === 'Online').length;
const owner = (window.g_rgProfileData?.personaname || document.querySelector('.profile_small_header_name')?.textContent || 'steam').trim();
deliver(`Found ${many(list.length, 'friend')}: ${playing} in game, ${online} online.`, body,
`steam-friends-${owner.replace(/[\\/:*?"<>|\s]+/g, '_')}.${FORMAT}`);
return list.length;
})();
🛡️ Chrome says “Don't paste code…”? That's normal. Type allow pasting in the console, press Enter and paste again. You only need to do it once.
Why does Chrome warn me?
Chrome shows this the first time anyone pastes into the console, to protect people from scams that ask them to paste unknown code. It's right to warn you, and that's why this script is fully visible above: 117 commented lines that send nothing anywhere and never touch your passwords or cookies. Why it's safe.
Rather not use the console? Drag the Export Steam friends button to your bookmarks bar and click it on steamcommunity.com. No warning that way.
Bookmarklet: drag the middle button to your bookmarks bar, open steamcommunity.com and click the bookmark. It runs the same script with the options above.
- Sends nothing anywhere. No fetch, XHR or external scripts. The only network activity is steamcommunity.com itself loading your list.
- Never touches your login. It doesn't read cookies, passwords, tokens or browser storage.
- Only runs on steamcommunity.com. Anywhere else it stops before doing anything.
- Short and readable. 117 commented lines, not minified or obfuscated.
- Shows its progress on the page. A small box tells you what it's doing and offers Download or Copy at the end.
- Same code for everyone. SHA-256 of the default version:
afef6951b7cd695d…
Verify it yourself in 30 seconds
- Read it: every line is above, with comments.
- Search the code for
fetch,XMLHttpRequest,cookie,localStorageoreval. None of them appear. - Open the Network tab before running it: you'll only see requests to steamcommunity.com.
How to use it
- Sign in on steamcommunity.com and open your Friends page (Profile > Friends, or go straight to
steamcommunity.com/my/friends). - Open the console: F12 or Ctrl+Shift+J (Cmd+Option+J on Mac). If Chrome asks, type
allow pastingand press Enter. - Copy the script, paste it in the console and press Enter. It reads the list the page already shows and offers the file straight away.
What you get
One row per friend: name, nickname (if you gave them one), status (in game, online or offline), the game they are playing right now, SteamID64 and profile link. The SteamID64 never changes, even if they change their name or custom URL, so you can always find them again. Choose TXT for a plain “Name – link” list.
Why back it up?
Steam has no export for friends. If your account is banned, hacked or you start a new one, the list is gone and finding people again by name is guesswork. A CSV with SteamID64s takes a second and lets you re-add everyone.
FAQ
Does Steam have a way to export my friends list?
No. Steam only shows the list, and the data request to Steam Support takes days. This script saves the list you already have open as a spreadsheet in a second.
Why would I back up my friends?
If your account is banned, hacked or you move to a new one, the friends list is gone. With the SteamID64 and profile link of each friend you can find and re-add them.
Do I need an API key or to give my password?
No. The script reads the Friends page in your own tab, with the session you already have. It sends nothing anywhere and never touches your password.
Can I export someone else's friends?
Yes, if their friends list is public. If it says 0 friends, the list is private.
Why is "Playing" empty for most friends?
It only shows the game a friend is playing right now. Steam doesn't show the date you became friends on this page, so it can't be exported.
