Skip to content

Instantly share code, notes, and snippets.

@delineas
Created July 5, 2026 10:41
Show Gist options
  • Select an option

  • Save delineas/8dbd1b91ea384eb7bd1b98874bcb9209 to your computer and use it in GitHub Desktop.

Select an option

Save delineas/8dbd1b91ea384eb7bd1b98874bcb9209 to your computer and use it in GitHub Desktop.
Extract Youtube titles from Dev Tools console
(async () => {
const LIMIT = 100;
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
const getTitles = () => {
const candidates = [
...document.querySelectorAll('a#video-title'),
...document.querySelectorAll('a[title][href*="/watch"]'),
...document.querySelectorAll('a[aria-label][href*="/watch"]')
];
const titles = candidates
.map((el) => {
const byTitle = el.getAttribute('title')?.trim();
const byText = el.textContent?.trim();
const byAria = el
.getAttribute('aria-label')
?.replace(/\s+de\s+.+$/i, '')
?.replace(/\s+by\s+.+$/i, '')
?.trim();
return byTitle || byText || byAria;
})
.filter(Boolean)
.map((title) => title.replace(/\s+/g, ' ').trim());
return [...new Set(titles)].slice(0, LIMIT);
};
let previousCount = 0;
let stableRounds = 0;
console.log('Buscando títulos...');
while (getTitles().length < LIMIT && stableRounds < 4) {
window.scrollTo(0, document.documentElement.scrollHeight);
await sleep(1200);
const currentCount = getTitles().length;
console.log(`Títulos encontrados: ${currentCount}`);
if (currentCount === previousCount) {
stableRounds++;
} else {
stableRounds = 0;
previousCount = currentCount;
}
}
const titles = getTitles();
const text = titles.join('\n');
const oldPanel = document.querySelector('#yt-title-copy-panel');
if (oldPanel) oldPanel.remove();
const panel = document.createElement('div');
panel.id = 'yt-title-copy-panel';
Object.assign(panel.style, {
position: 'fixed',
top: '20px',
right: '20px',
zIndex: '999999',
width: '420px',
maxWidth: 'calc(100vw - 40px)',
background: '#111',
color: '#fff',
border: '1px solid #444',
borderRadius: '12px',
padding: '16px',
fontFamily: 'system-ui, sans-serif',
boxShadow: '0 10px 40px rgba(0,0,0,.45)'
});
const title = document.createElement('div');
title.textContent = `${titles.length} títulos encontrados`;
Object.assign(title.style, {
fontSize: '16px',
fontWeight: '700',
marginBottom: '8px'
});
const textarea = document.createElement('textarea');
textarea.value = text;
Object.assign(textarea.style, {
width: '100%',
height: '260px',
boxSizing: 'border-box',
background: '#222',
color: '#fff',
border: '1px solid #555',
borderRadius: '8px',
padding: '10px',
fontFamily: 'monospace',
fontSize: '13px'
});
const buttons = document.createElement('div');
Object.assign(buttons.style, {
display: 'flex',
gap: '8px',
marginTop: '10px'
});
const copyButton = document.createElement('button');
copyButton.textContent = 'Copiar títulos';
Object.assign(copyButton.style, {
flex: '1',
padding: '10px',
border: '0',
borderRadius: '8px',
cursor: 'pointer',
fontWeight: '700'
});
const closeButton = document.createElement('button');
closeButton.textContent = 'Cerrar';
Object.assign(closeButton.style, {
padding: '10px',
border: '0',
borderRadius: '8px',
cursor: 'pointer'
});
copyButton.addEventListener('click', async () => {
textarea.focus();
textarea.select();
try {
await navigator.clipboard.writeText(text);
copyButton.textContent = 'Copiado ✅';
console.log(`Copiados ${titles.length} títulos al portapapeles.`);
} catch (err) {
const ok = document.execCommand('copy');
copyButton.textContent = ok ? 'Copiado ✅' : 'Copia manualmente';
console.log(text);
}
});
closeButton.addEventListener('click', () => {
panel.remove();
});
buttons.appendChild(copyButton);
buttons.appendChild(closeButton);
panel.appendChild(title);
panel.appendChild(textarea);
panel.appendChild(buttons);
document.body.appendChild(panel);
console.log(`Listos ${titles.length} títulos:`);
console.log(text);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment