Greasy Fork is available in English.

Altaireh TikTok Video Downloader V4

Download TikTok Videos Without A Watermark

  1. // ==UserScript==
  2. // @name Altaireh TikTok Video Downloader V4
  3. // @namespace none
  4. // @version 4.0
  5. // @description Download TikTok Videos Without A Watermark
  6. // @author altaireh
  7. // @match *://*.tiktok.com/*
  8. // @icon http://i.hmp.me/m/a0a089663971fa7ca3e9cdc2264ce7b4.png
  9. // @grant GM_xmlhttpRequest
  10. // @grant GM_download
  11. // @grant GM_getResourceURL
  12. // @resource BUTTON_IMG http://i.hmp.me/m/3025e92fff4d4d7fa8e0642fb6cfe270.png
  13. // ==/UserScript==
  14.  
  15. (function() {
  16. 'use strict';
  17.  
  18. const FILE_NAME = 'Altaireh.mp4';
  19.  
  20. const download = (url) => GM_xmlhttpRequest({
  21. method: 'GET',
  22. url,
  23. responseType: 'blob',
  24. onload: ({ response }) => GM_download({
  25. url: URL.createObjectURL(response),
  26. name: FILE_NAME
  27. })
  28. });
  29.  
  30. const manageVideoButtons = (video) => {
  31. let button;
  32. const buttonActions = {
  33. mouseover: () => {
  34. if (!button) {
  35. button = document.createElement('img');
  36. button.src = GM_getResourceURL('BUTTON_IMG');
  37. button.style.cssText = 'position: absolute; left: 10px; top: 50%; transform: translateY(-50%); z-index: 1000; width: 50px; height: 50px; cursor: pointer;';
  38. button.onclick = (e) => {
  39. e.stopPropagation();
  40. e.preventDefault();
  41. download(video.src || video.querySelector('source')?.src);
  42. };
  43. video.parentNode.appendChild(button);
  44. }
  45. },
  46. mouseout: (e) => {
  47. if (!video.contains(e.relatedTarget) && (!button || !button.contains(e.relatedTarget))) {
  48. button.remove();
  49. button = null;
  50. }
  51. }
  52. };
  53. Object.keys(buttonActions).forEach(event => video.addEventListener(event, buttonActions[event]));
  54. };
  55.  
  56. new MutationObserver(() => {
  57. document.querySelectorAll('video:not(.processed)').forEach((video) => {
  58. video.classList.add('processed');
  59. manageVideoButtons(video);
  60. });
  61. }).observe(document.body, { childList: true, subtree: true });
  62. })();