OnlyFans Free Subscriptions Filter (All Free Types)

Hide all non-free subscription cards on OnlyFans expired subscriptions page, keeping any type of "free" cards

Aby zainstalować ten skrypt, wymagana jest instalacje jednego z następujących rozszerzeń: Tampermonkey, Greasemonkey lub Violentmonkey.

You will need to install an extension such as Tampermonkey to install this script.

Aby zainstalować ten skrypt, wymagana jest instalacje jednego z następujących rozszerzeń: Tampermonkey, Violentmonkey.

Aby zainstalować ten skrypt, wymagana będzie instalacja rozszerzenia Tampermonkey lub Userscripts.

You will need to install an extension such as Tampermonkey to install this script.

Aby zainstalować ten skrypt, musisz zainstalować rozszerzenie menedżera skryptów użytkownika.

(Mam już menedżera skryptów użytkownika, pozwól mi to zainstalować!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

Będziesz musiał zainstalować rozszerzenie menedżera stylów użytkownika, aby zainstalować ten styl.

Będziesz musiał zainstalować rozszerzenie menedżera stylów użytkownika, aby zainstalować ten styl.

Musisz zainstalować rozszerzenie menedżera stylów użytkownika, aby zainstalować ten styl.

(Mam już menedżera stylów użytkownika, pozwól mi to zainstalować!)

// ==UserScript==
// @name         OnlyFans Free Subscriptions Filter (All Free Types)
// @namespace    https://greasyfork.org/en/users/318296-thomased
// @version      1.4.3
// @description  Hide all non-free subscription cards on OnlyFans expired subscriptions page, keeping any type of "free" cards
// @author       Gemini 3 Pro (previously ChatGPT 5.2 Thinking)
// @icon         https://static2.onlyfans.com/static/prod/f/202512181451-75a62e2193/icons/favicon-32x32.png
// @match        https://onlyfans.com/my/collections/user-lists/subscriptions/expired?paid=0
// @grant        none
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // Check if a button contains the word "free" (any case)
    function isFreeCard(btn) {
        if (!btn) return false;
        const textSpans = btn.querySelectorAll('span');
        for (const span of textSpans) {
            if (span.textContent.toLowerCase().includes('free')) return true;
        }
        return false;
    }

    // Hide card if it is not a free card
    function filterCard(card) {
        const btn = card.querySelector('div.m-rounded.m-flex.m-space-between.m-lg.g-btn[role="button"]');
        if (!isFreeCard(btn)) {
            card.style.display = 'none';
        } else {
            card.style.display = '';
        }
    }

    // Filter all cards on the page
    function filterAllCards() {
        document.querySelectorAll('.b-users__item.m-subscriptions.m-model-card, .b-offer-join__btn').forEach(filterCard);
    }

    // Run immediately on script load
    filterAllCards();

    // Observe dynamically loaded cards in the scrollable list
    const scroller = document.querySelector('.vue-recycle-scroller');
    if (scroller) {
        const observer = new MutationObserver(() => filterAllCards());
        observer.observe(scroller, { childList: true, subtree: true });
    }

    // Extra check for dynamically loaded content every 2 seconds
    setInterval(filterAllCards, 2000);
})();