pyofsDB (0.1.0)
Installation
pip install --index-url pyofsDBAbout this package
Read-only access to the SQLite databases produced by OF-Scraper
pyofsDB
Read-only access to the SQLite databases produced by OF-Scraper.
Extracted from pyofscraperstash so more than one consumer can share it. The databases are treated as strictly read-only — this package never writes to them.
What it gives you
- Discovery — find creator databases from a save location and metadata template, optionally filtered by creator or modification date.
- Loading — copy a database into memory via SQLite's backup API before querying, which matters when the files live on NFS.
- Schema detection — OF-Scraper's schema varies by the version that created each file;
SchemaDetectorreports theschema_flagsa given database carries. - Models — SQLAlchemy models for
medias,labels,profiles,models, and the five content tables (posts,stories,messages,products,others). - Queries — read-only helpers over those models.
Usage
import asyncio
from pyofsdb import DatabaseLoader, get_labels_by_post, get_profile_by_username
async def main() -> None:
loader = DatabaseLoader(save_location="/data/OnlyFans")
# Discover every creator database, or load one path directly
for path in await loader.find_database_files():
model_db = await loader.load_database(path)
session = model_db["session"]
profile = await get_profile_by_username(session, model_db["model_username"])
if profile:
labels = await get_labels_by_post(session, profile.user_id)
print(model_db["model_username"], len(labels))
await loader.dispose_model(path)
await loader.close()
asyncio.run(main())
DatabaseLoader takes its configuration as arguments rather than reading a global:
| Argument | Meaning |
|---|---|
save_location |
Root directory OF-Scraper writes to; substituted for {save_location} |
metadata_format |
Template for a creator's metadata directory. Defaults to {save_location}/meta/OnlyFans/{model_username}/Metadata. A template without {model_username} denotes a combined database |
models |
Restrict discovery to these creator usernames; omit to discover all |
Schema notes
OF-Scraper's schema differs between the versions that wrote each file. Measured across 78 production databases:
postsappears in six distinct column shapes.labels,models, andprofilesare absent entirely from some databases.mediasmay lackposted_at,duration,unlocked,hash, andmodel_id; the models mark thesedeferredso they are not selected unless accessed.alembic_versionis not a usable discriminator — most databases have no row, and those that do carry several different versions. Useschema_flags, whichload_databasereturns.
profiles has no model_id column in any known database. The creator's OF id lives in profiles.user_id, and carries the same value as models.model_id.
Logging
This package logs through the standard library logging module so the consuming application keeps control of handlers. Applications using loguru can forward records with loguru's InterceptHandler pattern.
Requirements
Python >=3.12, plus sqlalchemy, aiosqlite, and greenlet.