Basic Ad Blocker & Anti-Adblock Defeater (UserScript)

A basic UserScript to attempt blocking common ads, including pop-up video ads and unwanted new tab redirects, and some anti-adblock detection methods.

  1. // ==UserScript==
  2. // @name Basic Ad Blocker & Anti-Adblock Defeater (UserScript)
  3. // @namespace http://tampermonkey.net/
  4. // @version 2.1
  5. // @description A basic UserScript to attempt blocking common ads, including pop-up video ads and unwanted new tab redirects, and some anti-adblock detection methods.
  6. // @author Snow2122
  7. // @license MIT
  8. // @match *://*/*
  9. // @grant none
  10. // @run-at document-start
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. // --- Configuration ---
  17. // A list of common ad-related CSS selectors to hide or remove.
  18. // This list is based on common patterns found in advertising elements.
  19. const adSelectors = [
  20. // Generic ad containers
  21. '.ad', '.ads', '.advert', '.ad-container', '.banner-ad', '.google-ad',
  22. '.top-ad', '.bottom-ad', '.sidebar-ad', '.popup-ad',
  23. // Common element IDs
  24. '#ad', '#ads', '#advertisement', '#banner', '#google_ads_iframe',
  25. // Elements commonly used by ad networks or for injecting ads
  26. 'iframe[src*="adserver"]', 'iframe[src*="doubleclick.net"]',
  27. 'iframe[src*="googlesyndication.com"]', 'iframe[src*="adnxs.com"]',
  28. 'iframe[src*="taboola.com"]', 'iframe[src*="outbrain.com"]',
  29. 'iframe[src*="mgid.com"]', 'iframe[src*="monetize"]',
  30. 'div[id*="ad_"]', 'div[class*="ad_"]',
  31. 'div[id*="banner"]', 'div[class*="banner"]',
  32. 'div[id*="advert"]', 'div[class*="advert"]',
  33. 'div[data-google-query-id]', // Google AdSense specific
  34. // Elements often associated with "suggested content" or native ads
  35. '.native-ad', '.recommended-content', '.sponsored-content',
  36. // Pop-up related
  37. '.modal-backdrop', '.ad-popup-overlay', '.no-scroll',
  38. 'body.adblock-active', // Some sites add this class when detecting adblock
  39. 'div[style*="z-index: 99999"]', // Common for pop-ups
  40. 'div[style*="position: fixed"]', // Common for sticky ads/pop-ups
  41.  
  42. // --- Selectors specifically for video ads ---
  43. 'video', // Directly target video tags
  44. 'div[class*="video-ad"]', 'div[id*="video-ad"]', // Common video ad containers
  45. 'div[class*="video-overlay"]', 'div[id*="video-overlay"]', // Overlays often used for video pop-ups
  46. 'div[class*="video-player-ad"]', 'div[id*="video-player-ad"]', // More specific video player ad identifiers
  47. 'iframe[src*="videoplaza.tv"]', // Known video ad server
  48. 'iframe[src*="adform.net"]', // Known video ad server
  49. ];
  50.  
  51. // CSS rules to hide elements immediately. This is injected into the <head>.
  52. // Using !important to try and override inline styles.
  53. const hideCss = adSelectors.join(', ') + ' { display: none !important; visibility: hidden !important; }';
  54.  
  55. // Anti-adblock detection circumvention attempts.
  56. // These are common variables or functions websites might check.
  57. const antiAdblockDefeaters = {
  58. // Common global variables checked by adblock detection scripts
  59. 'AdBlock': false,
  60. 'adblock': false,
  61. 'blockAdblock': false,
  62. '_AdBlock_': false,
  63. 'canRunAds': true, // Some scripts check this
  64. // Overriding common detection functions/properties
  65. 'checkAdblock': () => false,
  66. 'isAdblockActive': false,
  67. };
  68.  
  69. // --- New blacklist for unwanted pop-up/redirect URLs ---
  70. const popupRedirectBlacklist = [
  71. 'doubleclick.net', 'googlesyndication.com', 'adserver', 'popads.net',
  72. 'onclickads.net', 'admaven.com', 'redirect.', 'trafficjunky.net',
  73. 'exoclick.com', 'propellerads.com', 'adsterra.com', 'mgid.com',
  74. 'popunder.', 'popcash.net', 'cpm-gate.com', 'adclick', 'ad-track'
  75. ];
  76.  
  77. // --- Core Functions ---
  78.  
  79. /**
  80. * Injects CSS rules into the document head to hide ad elements.
  81. * This runs very early to hide ads before they are fully rendered.
  82. */
  83. function injectHideCss() {
  84. const style = document.createElement('style');
  85. style.type = 'text/css';
  86. style.appendChild(document.createTextNode(hideCss));
  87. document.head.appendChild(style);
  88. console.log('[Basic Ad Blocker] Injected CSS to hide ads.');
  89. }
  90.  
  91. /**
  92. * Attempts to apply anti-adblock detection circumvention.
  93. * This tries to make the browser appear as if no ad blocker is present.
  94. */
  95. function circumventAntiAdblock() {
  96. for (const prop in antiAdblockDefeaters) {
  97. if (Object.prototype.hasOwnProperty.call(antiAdblockDefeaters, prop)) {
  98. try {
  99. // Try to define a property on window to mimic no adblocker
  100. Object.defineProperty(window, prop, {
  101. value: antiAdblockDefeaters[prop],
  102. writable: false, // Make it read-only if possible
  103. configurable: true // Allow re-definition if needed
  104. });
  105. console.log(`[Basic Ad Blocker] Set window.${prop} to ${antiAdblockDefeaters[prop]}`);
  106. } catch (e) {
  107. console.warn(`[Basic Ad Blocker] Failed to define window.${prop}:`, e);
  108. // Fallback for strict environments
  109. window[prop] = antiAdblockDefeaters[prop];
  110. }
  111. }
  112. }
  113.  
  114. // Override common element dimension checks for anti-adblock
  115. // Websites might create a dummy ad div and check its size.
  116. const originalOffsetWidth = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'offsetWidth');
  117. const originalOffsetHeight = Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'offsetHeight');
  118.  
  119. if (originalOffsetWidth) {
  120. Object.defineProperty(HTMLElement.prototype, 'offsetWidth', {
  121. get: function() {
  122. // If the element has common ad-related attributes, return a non-zero size
  123. if (this.id && this.id.includes('ad') || this.className && this.className.includes('ad')) {
  124. return 100; // Return a plausible size
  125. }
  126. return originalOffsetWidth.get.apply(this);
  127. },
  128. configurable: true
  129. });
  130. }
  131.  
  132. if (originalOffsetHeight) {
  133. Object.defineProperty(HTMLElement.prototype, 'offsetHeight', {
  134. get: function() {
  135. // If the element has common ad-related attributes, return a non-zero size
  136. if (this.id && this.id.includes('ad') || this.className && this.className.includes('ad')) {
  137. return 100; // Return a plausible size
  138. }
  139. return originalOffsetHeight.get.apply(this);
  140. },
  141. configurable: true
  142. });
  143. }
  144. console.log('[Basic Ad Blocker] Attempted to circumvent anti-adblock size checks.');
  145. }
  146.  
  147. /**
  148. * Overrides window.open to block unwanted pop-up and redirect tabs.
  149. */
  150. function blockPopunders() {
  151. const originalWindowOpen = window.open;
  152.  
  153. window.open = function(url, name, features) {
  154. // Check if the URL matches any of the blacklisted patterns
  155. const isBlocked = popupRedirectBlacklist.some(pattern => url && url.includes(pattern));
  156.  
  157. if (isBlocked) {
  158. console.warn(`[Basic Ad Blocker] Blocked pop-under/redirect attempt to: ${url}`);
  159. return null; // Prevent the window from opening
  160. }
  161.  
  162. // If not blocked, call the original window.open
  163. return originalWindowOpen.apply(this, arguments);
  164. };
  165. console.log('[Basic Ad Blocker] window.open override active for pop-under blocking.');
  166. }
  167.  
  168.  
  169. /**
  170. * Removes or hides elements matching ad selectors.
  171. * This function can be called repeatedly, e.g., on DOM mutations.
  172. * @param {HTMLElement | Document} container - The element or document to search within.
  173. */
  174. function blockAds(container = document) {
  175. let blockedCount = 0;
  176. adSelectors.forEach(selector => {
  177. try {
  178. const elements = container.querySelectorAll(selector);
  179. elements.forEach(el => {
  180. // Check if the element is already hidden by our CSS
  181. // If not, hide it with inline style or remove it if it's an iframe
  182. if (el.style.display !== 'none' && el.style.visibility !== 'hidden') {
  183. if (el.tagName === 'IFRAME') {
  184. el.remove(); // Removing iframes is more effective for blocking content
  185. console.log(`[Basic Ad Blocker] Removed iframe: ${selector}`);
  186. } else if (el.tagName === 'VIDEO') {
  187. // For video elements, try to pause and remove source before removing
  188. if (!el.paused) el.pause();
  189. el.src = ''; // Clear the video source
  190. // Remove child <source> elements if any
  191. while (el.firstChild) {
  192. el.removeChild(el.firstChild);
  193. }
  194. el.remove(); // Remove the video element entirely
  195. console.log(`[Basic Ad Blocker] Removed video ad: ${selector}`);
  196. }
  197. else {
  198. el.style.setProperty('display', 'none', 'important');
  199. el.style.setProperty('visibility', 'hidden', 'important');
  200. console.log(`[Basic Ad Blocker] Hidden element: ${selector}`);
  201. }
  202. blockedCount++;
  203. }
  204. });
  205. } catch (e) {
  206. console.error(`[Basic Ad Blocker] Error querying selector ${selector}:`, e);
  207. }
  208. });
  209. if (blockedCount > 0) {
  210. console.log(`[Basic Ad Blocker] Blocked ${blockedCount} elements.`);
  211. }
  212. }
  213.  
  214. /**
  215. * Initializes the MutationObserver to watch for DOM changes.
  216. * When new nodes are added, it re-applies ad-blocking logic.
  217. */
  218. function setupMutationObserver() {
  219. const observer = new MutationObserver(mutations => {
  220. mutations.forEach(mutation => {
  221. if (mutation.addedNodes.length > 0) {
  222. mutation.addedNodes.forEach(node => {
  223. // Only process element nodes
  224. if (node.nodeType === 1) { // Node.ELEMENT_NODE
  225. blockAds(node);
  226. }
  227. });
  228. }
  229. });
  230. });
  231.  
  232. // Start observing the entire document body for child list changes and subtree changes
  233. observer.observe(document.body, { childList: true, subtree: true });
  234. console.log('[Basic Ad Blocker] MutationObserver set up.');
  235. }
  236.  
  237. // --- Execution Flow ---
  238.  
  239. // 1. Run anti-adblock circumvention attempts immediately
  240. // before most scripts have a chance to run their checks.
  241. circumventAntiAdblock();
  242.  
  243. // 2. Override window.open to block pop-unders and unwanted redirects.
  244. blockPopunders();
  245.  
  246. // 3. Inject CSS rules at document-start to hide elements early.
  247. // This is the fastest way to get visual hiding in place.
  248. injectHideCss();
  249.  
  250. // 4. Perform an initial ad blocking pass on the existing document.
  251. // This catches elements present in the initial HTML.
  252. blockAds();
  253.  
  254. // 5. Set up a MutationObserver to catch dynamically loaded ads or elements
  255. // that change after the initial page load. This ensures continuous blocking.
  256. // Wait for the document body to be available before setting up the observer.
  257. if (document.body) {
  258. setupMutationObserver();
  259. } else {
  260. // If body is not yet available (e.g., very early in document-start),
  261. // wait for DOMContentLoaded to ensure body exists.
  262. document.addEventListener('DOMContentLoaded', setupMutationObserver);
  263. }
  264.  
  265. console.log('[Basic Ad Blocker] UserScript initialized.');
  266.  
  267. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址