Skip to content

Instantly share code, notes, and snippets.

@alana314
Last active December 17, 2025 12:45
Show Gist options
  • Select an option

  • Save alana314/6bdc9af962fd8620a4fb to your computer and use it in GitHub Desktop.

Select an option

Save alana314/6bdc9af962fd8620a4fb to your computer and use it in GitHub Desktop.
//Now with less jquery
//1) go to your my-list page, and scroll to the bottom to make sure it's all loaded:
//http://www.netflix.com/browse/my-list
//2) Next, paste this in your developer tools console and hit enter:
[...document.querySelectorAll('.slider [aria-label]')].map(ele => ele.getAttribute('aria-label'))
//or use this to copy the list to your clipboard:
copy([...document.querySelectorAll('.slider [aria-label]')].map(ele => ele.getAttribute('aria-label')))
@alana314
Copy link
Author

Updated this to not use jquery. In my other gists I also made a script to export a soundcloud playlist

@joyblanks
Copy link

joyblanks commented Jan 5, 2020

Thanks! I could export all titles and then I had to figure out how to add them to my new profile.
Found a very patchy way but did the job. Hope someone will need this.

1. Login & Select your old Account -> Profile
2. Go to My List (old profile)
3. Run this code in your Browser Developer console to Export and save My List

var tmpList = (function() {
    var list = []
    document.querySelectorAll('.title-card a[aria-label]').forEach(
        function(item) {
            try {
                list.push({
                    name: item.getAttribute('aria-label'),
                    link: ("https://www.netflix.com" + item.getAttribute("href").split("?")[0]).replace('watch', 'title')
                })
            } catch (err) {
                console.error("ERROR: Ignored err", err, item)
            }
        })
    return (JSON.stringify(list));
}());
localStorage.setItem('tmpList',tmpList);

4. Logout old account
5. Login & Select your new Account -> Profile
6. Run this Code in your Browser Developer console to Import My List saved in step 3

(function(){
  var list = JSON.parse(localStorage.getItem('tmpList'))
  var counter = 0;
  function openWin(e){
    var popup;
    popup = window.open(list[e].link);
    popup.onload = function(){
      setTimeout(function(){
        if(popup.document.querySelector('.nf-flat-button-icon-mylist-add + span')){
          popup.document.querySelector('.nf-flat-button-icon-mylist-add + span').click();
          setTimeout(function(){popup.close()}, 500);
          console.log('Added', list[e].name);
        } else {
          popup.close();
          console.log('Already added', list[e].name);
        }
      }, 500)
    }
    var timer = setInterval(function() { 
      if(popup && popup.closed) {
        clearInterval(timer);
        if(list.length-1 > counter){
          openWin(++counter);
        } else {
          console.log('Added');
          localStorage.removeItem('tmpList');
        }
      }
    }, 1000);
  }
  openWin(counter)
}())

7. Done

@alana314
Copy link
Author

alana314 commented Jan 6, 2020

@joyblanks Fancy! Thanks!

@jklingberg
Copy link

@joyblanks, Awesome!

@mehmet-demir
Copy link

mehmet-demir commented Feb 19, 2020

jhult's suggestion - "netflix-list-exporter" extension was an easier solution. Thanks.

@shahsahilj
Copy link

Is there a way to transfer the viewing history from one account? I know I can export it to a file, but then how do I import it in another profile?

@kghastie
Copy link

This works for me to generate a json or unquoted csv version of the titles and suggested ratings from the DVD In Queue page. (Yes, I still have a DVD account what do you want from me!?) Doesn't pull "Saved items" (the ones that aren't available at this time).

titles=[...document.querySelectorAll('#inqueueList .title.ondelhide')].map(ele => ele.text)
ratings=[...document.querySelectorAll('#inqueueList .starbar')].map(ele => ele.getAttribute('data-rating'))

titles_ratings = []
for (var i = 0; i < titles.length; i++) {
 titles_ratings.push([titles[i].replace('\\"', ''), ratings[i]]) 
}

json = JSON.stringify(titles_ratings)

csv = titles_ratings.map(function(d){
    return d.join();
}).join('\n');

Example csv output:

Hamlet,3.3
The Lion King,4.1
Westworld,4.2
Westworld,4.2
Westworld,4.2
Alien vs. Predator,2.3

@PetrusKiendys
Copy link

Is there a way to transfer the viewing history from one account? I know I can export it to a file, but then how do I import it in another profile?

@shahsahilj You can't. The only reason this script works is because it scrapes DOM elements that are already exposed by the Netflix website.
To make an import script you would have to create a script to automate the reinsertion of the data. Which can be as easy as pushing it to the Netflix API if you can reverse engineer it or hope that there's an officially supported way.

TL;DR Exporting account info such as "My List" is easy.
Importing the same info is a bit more tricky.

@agwosdz
Copy link

agwosdz commented Sep 5, 2020

Thanks! I could export all titles and then I had to figure out how to add them to my new profile.
Found a very patchy way but did the job. Hope someone will need this.

1. Login & Select your old Account -> Profile
2. Go to My List (old profile)
3. Run this code in your Browser Developer console to Export and save My List

var tmpList = (function() {
    var list = []
    document.querySelectorAll('.title-card a[aria-label]').forEach(
        function(item) {
            try {
                list.push({
                    name: item.getAttribute('aria-label'),
                    link: ("https://www.netflix.com" + item.getAttribute("href").split("?")[0]).replace('watch', 'title')
                })
            } catch (err) {
                console.error("ERROR: Ignored err", err, item)
            }
        })
    return (JSON.stringify(list));
}());
localStorage.setItem('tmpList',tmpList);

4. Logout old account
5. Login & Select your new Account -> Profile
6. Run this Code in your Browser Developer console to Import My List saved in step 3

(function(){
  var list = JSON.parse(localStorage.getItem('tmpList'))
  var counter = 0;
  function openWin(e){
    var popup;
    popup = window.open(list[e].link);
    popup.onload = function(){
      setTimeout(function(){
        if(popup.document.querySelector('.nf-flat-button-icon-mylist-add + span')){
          popup.document.querySelector('.nf-flat-button-icon-mylist-add + span').click();
          setTimeout(function(){popup.close()}, 500);
          console.log('Added', list[e].name);
        } else {
          popup.close();
          console.log('Already added', list[e].name);
        }
      }, 500)
    }
    var timer = setInterval(function() { 
      if(popup && popup.closed) {
        clearInterval(timer);
        if(list.length-1 > counter){
          openWin(++counter);
        } else {
          console.log('Added');
          localStorage.removeItem('tmpList');
        }
      }
    }, 1000);
  }
  openWin(counter)
}())

7. Done

Thanks, but the code is not working for me.... Getting a cannot set property 'onload' of null

Any ideas?

@mmcmaster-au
Copy link

The exporting script worked for me, but I had issues with the importing script.

The Chrome popup blocker needs to be disabled while importing.
Settings -> Site Settings -> Popups and Redirects

Second, I modified the code as follows:

(function(){
  var list = JSON.parse(localStorage.getItem('tmpList'))
  var counter = 0;
  function openWin(e){
    var popup;
    popup = window.open(list[e].link);
    popup.onload = function(){
      setTimeout(function(){
        if(popup.document.querySelector('[data-uia="add-to-my-list"]')){
          popup.document.querySelector('[data-uia="add-to-my-list"]').click();
          setTimeout(function(){popup.close()}, 500);
          console.log('Added', list[e].name);
        } else {
          popup.close();
          console.log('Already added', list[e].name);
        }
      }, 500)
    }
    var timer = setInterval(function() { 
      if(popup && popup.closed) {
        clearInterval(timer);
        if(list.length-1 > counter){
          openWin(++counter);
        } else {
          console.log('Added');
          localStorage.removeItem('tmpList');
        }
      }
    }, 1000);
  }
  openWin(counter)
}())

@m1337v
Copy link

m1337v commented Jan 2, 2021

Does anyone have an idea how to hide movies if they are either upvoted or downvoted? I only have a solution for downvotes if they are "greyed out". Maybe one could combine the scripts from here with this one?

    // ==/UserScript==
var $ = window.jQuery;
setInterval(function(){
        $('.slider-item:has(.is-disliked)').remove();
}, 1000);

@dwhitz
Copy link

dwhitz commented Sep 3, 2022

I suggest to take a look to https://github.com/origamiofficial/docker-netflix-migrate for exporting and importing netflix ratings

@shubkb07
Copy link

shubkb07 commented Dec 17, 2025

New, Support extracting title, URL to watch and Image + description,
Best things is Auto Scroll,
Future proof for class change, time in config,
Option to skip description to make it fast.

Step 1: Go to Netflix - My List - https://www.netflix.com/browse/my-list
Step 2: Press Control + Shift + J on Windows/Linux or Command + Option + J on Mac
Step 3: Copy Paste Below script

(async () => {
  'use strict';

  /* ================= CONFIG ================= */
  const CONFIG = {
    collectDescription: true, // true = slow, false = FAST 
    scrollIntervalMs: 3000,
    noIncreaseTimeoutMs: 30000, 
    modalOpenTimeoutMs: 8000,
    modalCloseTimeoutMs: 8000,
  };

  /* ================= SELECTORS ================= */
  const ROW_SELECTOR =
    '.galleryLockups .rowContainer.rowContainer_title_card';

  const ITEM_SELECTOR =
    '.galleryLockups .rowContainer.rowContainer_title_card .slider-item .ptrack-content';

  const MODAL_SELECTOR =
    '.focus-trap-wrapper.previewModal--wrapper.detail-modal';

  const MODAL_DESCRIPTION_SELECTOR =
    '.previewModal--detailsMetadata-left p div';

  /* ================= UTILS ================= */
  const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
  const nowMs = () => Date.now();

  const waitFor = async (fn, timeoutMs, stepMs = 200) => {
    let waited = 0;
    while (waited < timeoutMs) {
      const res = fn();
      if (res) return res;
      await sleep(stepMs);
      waited += stepMs;
    }
    return null;
  };

  const scrollToBottom = () => {
    window.scrollTo({ top: document.body.scrollHeight, behavior: 'smooth'
    });
  };

  const getRowCount = () =>
    document.querySelectorAll(ROW_SELECTOR).length;

  const closeModalViaHistory = async () => {
    // Netflix modal is route-based
    window.history.back();

    // wait until modal is really gone
    await waitFor(
      () => !document.querySelector(MODAL_SELECTOR),
      CONFIG.modalCloseTimeoutMs
    );

    // animation buffer
    await sleep(300);
  };

  const downloadJson = (data) => {
    const fileName = `netflix_my_list_${nowMs()
    }.json`;
    const blob = new Blob([JSON.stringify(data,
      null,
      2)
    ],
    {
      type: 'application/json',
    });
    const a = document.createElement('a');
    a.href = URL.createObjectURL(blob);
    a.download = fileName;
    document.body.appendChild(a);
    a.click();
    a.remove();
    URL.revokeObjectURL(a.href);
  };

  /* ================= STEP 1: AUTO SCROLL ================= */
  console.log('[Netflix Export
  ] Loading all items…');

  let lastCount = 0;
  let lastIncreaseAt = nowMs();

  while (true) {
    scrollToBottom();
    await sleep(CONFIG.scrollIntervalMs);

    const count = getRowCount();
    if (count > lastCount) {
      lastCount = count;
      lastIncreaseAt = nowMs();
      console.log(`[Scroll
      ] Rows: ${count
      }`);
    } else if (nowMs() - lastIncreaseAt >= CONFIG.noIncreaseTimeoutMs) {
      break;
    }
  }
  /* ================= STEP 2: COLLECT DATA ================= */
  console.log('[Netflix Export
  ] Collecting titles…');

  const nodes = Array.from(document.querySelectorAll(ITEM_SELECTOR));
  const results = [];

  for (let i = 0; i < nodes.length; i++) {
    const node = nodes[i
    ];
    const link = node.querySelector('a');
    const img = node.querySelector('.boxart-container img');
    if (!link) continue;

    const entry = {
      index: i + 1,
      href: 'https: //www.netflix.com/' + link.getAttribute('href'),
      title: link.getAttribute('aria-label'),
      image: img?.getAttribute('src') || null,
      description: null,
    };

    if (CONFIG.collectDescription) {
      try {
        link.scrollIntoView({ block: 'center'
        });
        await sleep(400);
        link.click();

        const modal = await waitFor(
          () => document.querySelector(MODAL_SELECTOR),
          CONFIG.modalOpenTimeoutMs
        );

        if (modal) {
          const descEl = await waitFor(
            () => modal.querySelector(MODAL_DESCRIPTION_SELECTOR),
            CONFIG.modalOpenTimeoutMs
          );

          if (descEl) {
            entry.description = descEl.innerText.trim();
          }

          await closeModalViaHistory();
        }
      } catch (e) {
        console.warn(`[${entry.title
          }
        ] description failed`, e);
        await closeModalViaHistory();
      }
    }

    results.push(entry);
    console.log(`[Collected
    ] ${entry.title
    }`);
  }
  /* ================= EXPORT ================= */
  downloadJson(results);
  console.log('[Netflix Export
  ] DONE 🎉');
})();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment