Sleek YouTube Downloader

A simple tool that adds YouTube-style buttons for multi-format downloading. Lighter than most download scripts.

  1. // ==UserScript==
  2. // @name Sleek YouTube Downloader
  3. // @namespace https://github.com/thisismy-github
  4. // @description A simple tool that adds YouTube-style buttons for multi-format downloading. Lighter than most download scripts.
  5. // @author thisismy-github
  6. // @match https://www.youtube.com/
  7. // @match https://www.youtube.com/watch*
  8. // @match https://www.youtube.com/playlist*
  9. // @grant none
  10. // @license MIT
  11. // @run-at document-end
  12. // @version 3.2.0
  13. // ==/UserScript==
  14.  
  15.  
  16. // Valid formats: MP4 || MP3, WAV, M4A, WEBM, AAC, FLAC, OPUS, OGG
  17. const buttons = ["MP3", "MP4"];
  18.  
  19.  
  20. // There is no consistent variable for border-radius (button roundness) yet.
  21. // Old border-radius: 2px. New border-radius: 20px or higher.
  22. const cssText = `
  23. .download-button {
  24. border-radius: 20px;
  25. display: flex;
  26. flex-direction: row;
  27. cursor: pointer;
  28. background-color: var(--yt-spec-10-percent-layer);
  29. color: var(--yt-spec-text-secondary);
  30. padding: var(--yt-button-padding);
  31. margin: auto var(--ytd-subscribe-button-margin, 4px);
  32. white-space: nowrap;
  33. font-size: var(--ytd-tab-system-font-size, 1.4rem);
  34. font-weight: var(--ytd-tab-system-font-weight, 500);
  35. letter-spacing: var(--ytd-tab-system-letter-spacing, .007px);
  36. text-transform: var(--ytd-tab-system-text-transform, uppercase);
  37. }
  38. .download-button-text {
  39. --yt-formatted-string-deemphasize_-_display: initial;
  40. --yt-formatted-string-deemphasize-color: var(--yt-spec-text-secondary);
  41. --yt-formatted-string-deemphasize_-_margin-left: 4px;
  42. }
  43. .download-button-container {
  44. display: flex;
  45. flex-direction: row;
  46. }
  47. .download-playlist-button {
  48. margin-right: 8px;
  49. margin-left: 0px;
  50. }
  51. .download-playlist-button-text {
  52. color: #E4E4E4;
  53. }
  54. `;
  55.  
  56.  
  57. (function() {
  58. 'use strict';
  59. window.onload = () => {
  60.  
  61. // playlist pages will try to add the buttons repeatedly
  62. let playlistButtonsAdded = false;
  63.  
  64. window.addEventListener("yt-navigate-finish", () => {
  65. setTimeout(() => {
  66.  
  67. // apply css
  68. const style = document.createElement("style");
  69. style.type = "text/css";
  70. style.innerHTML = cssText;
  71. document.head.appendChild(style);
  72.  
  73. // check for playlist and create appropriate query
  74. let query = "#analytics-button:not(.download-panel)";
  75. let inPlaylist = location.href.includes("/playlist");
  76. if (inPlaylist && !playlistButtonsAdded) {
  77. query += ", div.metadata-buttons-wrapper:not(.download-panel)";
  78. playlistButtonsAdded = true;
  79. }
  80.  
  81. document.querySelectorAll(query).forEach(panel => {
  82.  
  83. // outer container (to flex buttons side-by-side)
  84. const container = document.createElement("div");
  85. container.classList.add("download-button-container");
  86.  
  87. for (let i = 0; i < buttons.length; i++) {
  88. const button = document.createElement("div"); // button
  89. button.classList.add("download-button");
  90. if (inPlaylist) { button.classList.add("download-playlist-button"); }
  91.  
  92. button.addEventListener("click", () => { // download function
  93. let link = encodeURIComponent(location.href);
  94. let format = buttons[i].toLowerCase();
  95. if (format === "mp4") { format = "7"; }
  96. window.open(`https://loader.to/?link=${ link }&f=${ format }&s=1&e=1&r=loader`);
  97. });
  98.  
  99. const buttonText = document.createElement("span"); // button text
  100. buttonText.classList.add("download-button-text");
  101. if (inPlaylist) { buttonText.classList.add("download-playlist-button-text"); }
  102. buttonText.innerHTML = buttons[i];
  103. button.appendChild(buttonText); // append text to button
  104. container.appendChild(button);
  105. }
  106.  
  107. panel.classList.add("download-panel");
  108. panel.insertBefore(container, panel.firstElementChild);
  109. });
  110. }, 200);
  111. });
  112. };
  113. })();