Data Analysis 10 min read

OnlyFans Revenue Per Subscriber: How to Calculate and Optimize ARPU Across Your Agency

Most agencies track total revenue. We track revenue per subscriber — and it changed how we evaluate creators, allocate chatters, and prioritize growth spend. Here is the full ARPU framework we use across our roster.

OFAPI Team ·

Six months in, a partner at a fund we were talking to asked us a single question: “Which creator is most efficient?” We were in a board-style call, four people on the other side, and none of us could answer. We knew total revenue. We knew subscriber counts. But efficient — revenue generated per fan, per dollar of chatter investment — we had no idea. We’d never calculated it.

We built a spreadsheet that night. What we found changed how we evaluate every creator on our roster.

Creator A generates $15,000 per month. Creator B generates $8,000 per month. Creator A looks like the priority — more resources, more chatter hours, more content investment. That logic is not wrong, but it is incomplete in a way that costs agencies money. We discovered this when we started looking at the denominator.

Creator A: $15,000 per month with 3,000 active fans. Revenue per subscriber: $5.00.

Creator B: $8,000 per month with 500 active fans. Revenue per subscriber: $16.00.

Creator B is generating more than three times the revenue per fan. Her chatters are more effective, her content is better matched to her audience, or her fan acquisition has been more targeted — probably some combination of all three. In absolute terms she looks like the smaller account. On a per-subscriber basis, she is running a meaningfully more efficient operation.

This realization changed how we think about everything from chatter allocation to growth investment to creator prioritization.

What ARPU Actually Measures

Average Revenue Per User — ARPU in the subscriber context — is total revenue divided by total active fans over a given period. On OnlyFans, the calculation is straightforward but the interpretation requires care.

Active fans is not the same as total subscribers. A fan who subscribed six months ago and has not opened a message since is not contributing to current revenue, and treating them as equivalent to an engaged fan inflates your denominator and deflates your apparent ARPU. For our calculations, we define active as a fan who has had at least one interaction or spend event in the trailing 30 days.

Revenue also needs to be broken down by type, because the composition of ARPU tells you different things than the total. A creator with $16 ARPU driven 80% by subscriptions is in a different position than a creator with $16 ARPU driven 60% by PPV. The first creator has predictable, recurring revenue but may have limited upside unless subscription price increases. The second creator has chatters who are actively converting, with more room to grow through better PPV strategy.

We track three sub-components separately:

Subscription ARPU: subscription revenue divided by total active fans. This is your floor — the predictable base that exists before chatters touch anything.

PPV ARPU: PPV revenue divided by total active fans. This is the chatter signal. High PPV ARPU means your chatters are converting. Low PPV ARPU is either a chatter problem or a content problem.

Tip ARPU: tip revenue divided by total active fans. Tips are the relationship signal. Fans who tip consistently have genuine emotional investment in the creator. High tip ARPU correlates with retention.

Pulling the Data

The /statistics/overview endpoint gives you the revenue totals. The /stats/fans data gives you the active fan count and spend breakdown. Here is the full ARPU calculation pipeline across a multi-creator roster:

import requests
from dataclasses import dataclass, field
from typing import Optional

API_KEY = "your_api_key"
BASE_URL = "http://157.180.79.226:4024/api/v1"
headers = {"X-API-Key": API_KEY}

@dataclass
class CreatorARPU:
    creator_id: str
    total_revenue: float = 0.0
    active_fans: int = 0
    sub_revenue: float = 0.0
    ppv_revenue: float = 0.0
    tip_revenue: float = 0.0
    total_arpu: float = 0.0
    sub_arpu: float = 0.0
    ppv_arpu: float = 0.0
    tip_arpu: float = 0.0
    revenue_mix: dict = field(default_factory=dict)

def fetch_creator_arpu(creator_id: str, period: str = "30d") -> CreatorARPU:
    """Calculate full ARPU breakdown for a single creator."""
    result = CreatorARPU(creator_id=creator_id)

    # Fetch overview statistics
    stats_resp = requests.get(
        f"{BASE_URL}/statistics/overview",
        headers=headers,
        params={"creatorId": creator_id, "period": period}
    )
    stats_resp.raise_for_status()
    stats = stats_resp.json().get("stats", {})

    result.total_revenue = float(stats.get("totalRevenue", 0))
    result.sub_revenue = float(stats.get("subscriptionRevenue", 0))
    result.ppv_revenue = float(stats.get("ppvRevenue", 0))
    result.tip_revenue = float(stats.get("tipRevenue", 0))

    # Fetch fan statistics for active fan count
    fans_resp = requests.get(
        f"{BASE_URL}/stats/fans",
        headers=headers,
        params={"creatorId": creator_id, "period": period, "activeOnly": True}
    )
    fans_resp.raise_for_status()
    fans_data = fans_resp.json()

    result.active_fans = int(fans_data.get("activeFanCount", 0))

    # Calculate ARPU components
    if result.active_fans > 0:
        result.total_arpu = result.total_revenue / result.active_fans
        result.sub_arpu = result.sub_revenue / result.active_fans
        result.ppv_arpu = result.ppv_revenue / result.active_fans
        result.tip_arpu = result.tip_revenue / result.active_fans

    # Revenue mix as percentages
    if result.total_revenue > 0:
        result.revenue_mix = {
            "subscription_pct": result.sub_revenue / result.total_revenue * 100,
            "ppv_pct": result.ppv_revenue / result.total_revenue * 100,
            "tip_pct": result.tip_revenue / result.total_revenue * 100,
        }

    return result

def agency_arpu_report(creator_ids: list) -> list:
    """Generate ARPU report for all creators, sorted by efficiency."""
    results = []
    for creator_id in creator_ids:
        try:
            arpu = fetch_creator_arpu(creator_id)
            results.append(arpu)
        except Exception as e:
            print(f"Error fetching {creator_id}: {e}")

    # Sort by total ARPU descending
    return sorted(results, key=lambda x: -x.total_arpu)

def print_arpu_report(results: list):
    print(f"\n{'Creator':<15} {'Fans':>8} {'Revenue':>10} {'ARPU':>8} {'Sub$':>8} {'PPV$':>8} {'Tip$':>8}")
    print("-" * 75)
    for r in results:
        print(
            f"{r.creator_id:<15} "
            f"{r.active_fans:>8,} "
            f"${r.total_revenue:>9,.0f} "
            f"${r.total_arpu:>7.2f} "
            f"${r.sub_arpu:>7.2f} "
            f"${r.ppv_arpu:>7.2f} "
            f"${r.tip_arpu:>7.2f}"
        )

    # Benchmarks
    if results:
        avg_arpu = sum(r.total_arpu for r in results) / len(results)
        top_arpu = results[0].total_arpu
        print(f"\nAgency Average ARPU: ${avg_arpu:.2f}")
        print(f"Top Performer ARPU:  ${top_arpu:.2f}")
        below_avg = [r for r in results if r.total_arpu < avg_arpu * 0.75]
        if below_avg:
            print(f"\nCreators below 75% of agency average (need attention):")
            for r in below_avg:
                print(f"  {r.creator_id}: ${r.total_arpu:.2f} ARPU ({r.active_fans:,} fans)")

creator_ids = ["creator_001", "creator_002", "creator_003", "creator_004", "creator_005"]
report = agency_arpu_report(creator_ids)
print_arpu_report(report)

The output gives you something the OnlyFans native dashboard cannot: every creator on your roster on the same scale, ranked by the metric that actually tells you how efficiently each account is being run.

What ARPU Reveals About Your Creators

The ARPU breakdown is diagnostic. Different patterns point to different problems and different interventions.

High total ARPU, high PPV ARPU: This creator has excellent chatters and content that converts. The question is whether the fan base can be grown — more fans at this efficiency level means proportionally more revenue.

High total ARPU, low PPV ARPU, high tip ARPU: Fans are deeply engaged but not being actively sold to. There may be money being left on the table. Review chatter PPV strategy for this creator.

Low total ARPU, high active fan count: This is the Creator A scenario — large audience, low monetization efficiency. Two possible causes: chatter quality issue, or wrong audience (fans acquired at low-cost who do not have PPV intent). Pull the top fan data to see if the high-spenders exist but are not numerous, or whether spend is flat across the board.

Low total ARPU, low active fan count: New account or recovering account. ARPU is less meaningful at small sample sizes — focus on absolute revenue until the fan base reaches a threshold where the ratios stabilize.

Sub ARPU equals total ARPU: Chatters are not converting any PPV. This is either a chatter problem or a content problem. Pull the PPV open rate data from the fan profiles and compare with other creators to determine which.

ARPU as a Growth Decision Framework

Once you have ARPU data across your roster, it changes how you allocate resources.

Growth investment — paid promotion, referral spend, content production budget — should go toward creators with high ARPU and room to grow fan count. Adding 500 fans to a creator with $16 ARPU generates $8,000 in monthly revenue. Adding 500 fans to a creator with $5 ARPU generates $2,500. The investment case is not even close.

Chatter hours are a fixed cost. When demand for chatter time exceeds supply — which happens when your roster grows faster than your team — ARPU tells you where to prioritize. High-ARPU creators with declining engagement scores need attention first. Low-ARPU creators may not need more chatter hours; they may need better chatter strategy.

Creator offboarding decisions become clearer. A creator with persistently low ARPU after several months of operation and active intervention is occupying roster capacity that could go to a higher-efficiency creator. ARPU gives you an objective framework for a difficult conversation.

Industry Benchmarks

Based on our internal data and what we have observed across the agency landscape, rough ARPU benchmarks by account type:

  • Starter accounts (under 500 active fans): $3–8 ARPU is typical. Revenue is subscription-heavy; chatters have not yet built the fan relationships needed for strong PPV conversion.
  • Mid-tier accounts (500–2,000 active fans): $8–15 ARPU. Well-run accounts in this range have established chatter workflows and consistent PPV revenue.
  • Established accounts (2,000+ active fans): $12–25+ ARPU. At this scale, efficient agencies are generating significant PPV and tip revenue on top of a strong subscription base.

An account running below $5 ARPU at any scale is a signal that something in the chatter workflow, content strategy, or fan acquisition funnel is not working. An account consistently above $20 ARPU has something replicable — study it and try to apply those patterns to the rest of your roster.


ARPU is not the only metric that matters, but it is the one that makes the most opaque part of agency performance — how efficiently each creator is being monetized — legible and comparable. Without it, you are managing by revenue rankings alone, which is a lagging indicator that tells you what happened but not why or where to intervene.

For a deeper look at how fan-level data feeds into ARPU analysis, see our post on building a custom OnlyFans CRM. For the fan retention strategy that keeps high-ARPU fans engaged, see our whale fan retention guide.

Start pulling ARPU data across your roster via OFAPI pricing, or review the statistics endpoints in the API documentation.

Ready to automate your OnlyFans operations?

Get full API access and start building in minutes.