Skip to main content
Most integrations don’t need Dynamic Rules. If you’re using the Access API or TypeScript SDK, request signing is handled automatically. Only read this guide if you’re making direct requests to OnlyFans APIs.

Overview

The Dynamic Rules API (/v2/dynamic-rules) provides the current signing parameters required to generate valid signatures for OnlyFans API requests. OnlyFans requires cryptographically signed requests and changes their signing requirements very frequently - sometimes multiple times per day.
Direct API calls require vigilance. OnlyFans rotates signing requirements frequently—hardcoded values stop working within hours, leading to 401/403 errors. Because dynamic rules depend on OnlyFans behaviour, plan for sudden changes and have fallbacks (circuit breakers, retries, status messaging) ready for temporary outages.

When You Need Dynamic Rules

Dynamic rules are required when:
  • Direct OnlyFans API Integration: Making requests directly to onlyfans.com APIs
  • Custom Proxy Solutions: Building your own request proxy system
  • Advanced Use Cases: Specific requirements that can’t use OFAuth’s Access API
Update Detection: Set up webhooks for proactive notifications, or watch for 400 “Please refresh the page” errors when making direct OnlyFans API requests.

When You Don’t Need Dynamic Rules

You can skip dynamic rules implementation if:
  • Using Access API: All OnlyFans requests go through OFAuth’s /v2/access endpoints
  • Standard Integration: Following OFAuth’s recommended integration patterns
  • Simplified Architecture: Want OFAuth to handle all OnlyFans API complexity

Why Dynamic Rules Are Essential

OnlyFans implements sophisticated anti-abuse measures that require:
  1. Cryptographic Signatures: Every API request must include a valid signature
  2. Current Parameters: Signing algorithm, fields, and formats change frequently
  3. Exact Implementation: Minor deviations result in rejected requests
  4. Real-time Updates: Rules can change multiple times per day without notice

What Happens Without Current Rules

  • Authentication Failures: 401/403 errors for all OnlyFans API requests
  • Service Interruption: Applications stop working until rules are updated
  • User Impact: Authentication flows fail, data access blocked

How OFAuth Solves This

OFAuth provides two solutions for handling OnlyFans’ complex signing requirements: 1. Access API (Recommended)
  • Automatic Signing: All request signing handled transparently
  • No Implementation Required: Use standard REST endpoints
  • Always Current: Signing rules updated automatically
  • Zero Maintenance: No code changes needed for rule updates
2. Dynamic Rules API (Advanced)
  • Real-time Monitoring: OFAuth tracks rule changes 24/7
  • Instant Access: Latest rules available via API immediately, and sent as a webhook event
  • Manual Signing: Use the /sign endpoint for custom implementations
  • High Availability: Multiple redundant systems ensure rule availability

Base URL

https://api.ofauth.com/v2/dynamic-rules

Authentication

All Dynamic Rules API requests require your API key:
apikey: YOUR_API_KEY

Access Control

Access to dynamic rules is available in two forms:
  • Current Rules (Paid): Real-time signing payloads delivered via API and webhooks. This is the add-on sold with OFAuth and includes 24/7 monitoring and SLA-backed uptime.
  • Public Rules (GitHub): Delayed snapshots published for the community at no cost. Grab them from github.com/deviint/onlyfans-dynamic-rules.

Core Endpoints

Get Current Rules

Retrieve the latest OnlyFans API rules and signing parameters.

Sign Request

Generate a signed request using current rules for OnlyFans API access.

Check Rules Status

Get the current status of dynamic rules without fetching the actual rules.

Implementation Guide

1. Fetch and Cache Rules

class RulesManager {
	constructor(apiKey) {
		this.apiKey = apiKey
		this.rules = null
		this.lastFetch = null
	}

	async getRules() {
		// Check if we need to fetch new rules
		if (!this.rules || this.shouldRefresh()) {
			await this.fetchRules()
		}
		return this.rules
	}

	async fetchRules() {
		const response = await fetch("https://api.ofauth.com/v2/dynamic-rules", {
			headers: { apikey: this.apiKey }
		})

		if (!response.ok) {
			throw new Error(`Failed to fetch rules: ${response.status}`)
		}

		const data = await response.json()
		this.rules = data
		this.lastFetch = Date.now()
	}

	shouldRefresh() {
		if (!this.rules || !this.lastFetch) return true
		// Refresh every 5 minutes or if rules are not current
		return Date.now() - this.lastFetch > 5 * 60 * 1000 || !this.rules.is_current
	}
}

2. Generate Signed Requests

class RequestSigner {
	constructor(rulesManager) {
		this.rulesManager = rulesManager
	}

	async signRequest(endpoint, userId = null) {
		const response = await fetch(
			"https://api.ofauth.com/v2/dynamic-rules/sign",
			{
				method: "POST",
				headers: {
					apikey: this.rulesManager.apiKey,
					"Content-Type": "application/json"
				},
				body: JSON.stringify({
					endpoint,
					...(userId && { "user-id": userId })
				})
			}
		)

		if (!response.ok) {
			throw new Error(`Signing failed: ${response.status}`)
		}

		return response.json()
	}

	async makeSignedRequest(endpoint, userId = null, options = {}) {
		const signedData = await this.signRequest(endpoint, userId)

		const headers = {
			...signedData.signed,
			"user-agent": "OnlyFans/1.0.0",
			accept: "application/json",
			...options.headers
		}

		return fetch(`https://onlyfans.com${endpoint}`, {
			...options,
			headers
		})
	}
}

3. Handle Rules Updates

Do NOT poll for rules updates. Only fetch new rules when you receive a 400 “Please refresh the page” error from OnlyFans APIs, or when you receive a webhook notification. Polling wastes resources and is not the intended usage pattern.
There are two proper ways to detect when rules need updating:
  1. Error-Driven (Reactive): Monitor for 400 “Please refresh the page” errors from OnlyFans APIs
  2. Webhook-Driven (Proactive): Set up a webhook endpoint to receive rules updates with the new rules included in the payload
class RequestSigner {
	constructor(rulesManager) {
		this.rulesManager = rulesManager
	}

	async makeSignedRequest(endpoint, userId = null, options = {}) {
		try {
			const signedData = await this.signRequest(endpoint, userId)
			
			const headers = {
				...signedData.signed,
				"user-agent": "Mozilla ...",
				accept: "application/json",
				...options.headers
			}

			const response = await fetch(`https://onlyfans.com${endpoint}`, {
				...options,
				headers
			})

			// ONLY refresh rules on 400 error from OnlyFans
			if (response.status === 400) {
				const body = await response.json()
				if (body?.error?.code === 401 && 
					body?.error?.message?.includes("Please refresh the page")) {
					console.log("Rules outdated, fetching new rules...")
					await this.rulesManager.fetchRules()
					// Retry the request with new rules
					return this.makeSignedRequest(endpoint, userId, options)
				}
			}

			return response
		} catch (error) {
			console.error("Request failed:", error)
			throw error
		}
	}
}
Webhook Payload Structure:
{
  "eventType": "rules.updated",
  "live": true,
  "data": {
    "rules": {
      "static_param": "staticp",
      "format": "{0}:{1}:{2}:{3}",
      "start": "start", 
      "end": "end",
      "prefix": "",
      "suffix": "",
      "checksum_constant": 123,
      "checksum_indexes": [1, 2, 3, 4, 5],
      "app_token": "current_app_token",
      "revision": "202501150001-abcdef"
    },
    "revision": "202501150001-abcdef"
  }
}
No API Call Required: The webhook includes the complete rules object in the payload, so you don’t need to make a separate API request to /v2/dynamic-rules when you receive the webhook.

Advanced Integration Patterns

Self-Signing Implementation

For high-volume applications, you can implement local signing after fetching rules:
import crypto from 'crypto';

function signRequest(rules, { endpoint, userId = null, time = null }) {
    const signTime = time || Math.floor(Date.now() / 1000).toString();
    
    const url = new URL(endpoint, 'https://onlyfans.com');
    const path = url.pathname + url.search;
    
    const message = [
        rules.static_param,
        signTime,
        path,
        userId || '0'
    ].join('\n');
    
    const shaHash = crypto.createHash('sha1').update(message).digest('hex');
    const hashBuffer = Buffer.from(shaHash, 'ascii');
    
    const checksum = rules.checksum_indexes.reduce((sum, index) => {
        return sum + hashBuffer[index];
    }, 0) + rules.checksum_constant;
    
    const sign = [
        rules.start,
        shaHash,
        Math.abs(checksum).toString(16),
        rules.end
    ].join(':');
    
    return {
        sign,
        time: signTime,
        'app-token': rules.app_token,
        'x-of-rev': rules.revision
    };
}

Error Handling

When making requests to OnlyFans APIs with signed headers, you may receive:
HTTP 400 Bad Request
{
  "error": {
    "code": 401,
    "message": "Please refresh the page"
  }
}
Solution: This indicates your rules are outdated. Fetch new rules and retry the request.
// Check OnlyFans API responses for this signal
if (response.status === 400) {
    const body = await response.json()
    if (body?.error?.code === 401 && 
        body?.error?.message?.includes("Please refresh the page")) {
        await rulesManager.fetchRules()
        // Retry your request with new rules
    }
}
This is one of two proper ways to detect rules updates. The other is setting up a webhook endpoint to receive proactive notifications.
{
  "error": "You don't have access to the latest rules, please upgrade your plan.",
  "is_current": true,
  "is_public": false,
  "is_early_access": true
}
Solution: Upgrade your subscription plan to access the latest rules tier.
{
  "error": "The rules are not up to date. Please try again later, or contact '[email protected]' if this issue persists.",
  "is_current": false,
  "is_public": true,
  "is_early_access": false,
}
Solution: Wait 30-60 seconds and retry. This typically happens during OnlyFans maintenance windows.
{
  "error": "Invalid method"
}
Solution: Ensure you’re using the correct HTTP method for each endpoint (GET for /, POST for /sign, GET for /status).

Best Practices

Rules Management

Cache Efficiently

Cache rules but refresh when is_current becomes false

Monitor Changes

Use webhooks or watch for 400 “Please refresh the page” errors

Handle Access Tiers

Design your app to gracefully handle different access levels

Auto-Retry Logic

Implement automatic rule refresh and request retry on 400 errors

Plan for Outages

Build fallback strategies for OnlyFans API disruptions

Error Handling

Implement robust error handling for third-party dependencies

Performance Optimization

For high-volume applications, implement local signing using the rules data rather than calling the /sign endpoint for every request.

Reliability Considerations

Production Readiness: OnlyFans is known for making sudden changes that can break integrations. When building production applications:
  • Implement circuit breakers to handle extended outages
  • Build retry logic with exponential backoff for temporary failures
  • Monitor error rates and have alerting in place
  • Consider rate limiting your own API calls to avoid overwhelming systems during recovery
  • Have a communication plan for when OnlyFans APIs are unavailable
  • Test your error handling regularly to ensure it works when needed

Migration Guide

From Legacy Signing

If you’re migrating from a legacy signing implementation:
  1. Replace static rules with dynamic rule fetching
  2. Update signing algorithms based on current rules structure
  3. Implement proper caching with is_current checks
  4. Add monitoring for rules changes using /status endpoint

Next Steps