> For the complete documentation index, see [llms.txt](https://cloakedkeys.gitbook.io/ofsc/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cloakedkeys.gitbook.io/ofsc/reference/config.md).

# config.json keys

> ℹ️ This page is copied from the fork's `reference/` folder and is regenerated there. Don't edit it here; run `scripts/sync_reference.py` to refresh it.

## `config.json` reference

Every key `config.json` holds, in the order the file is written (`ofscraper/utils/config/schema.py`). Defaults are what a new config gets.

Each key lists these fields, when they apply: **Default**, **Read by** (the getter), **Default from** (the environment default behind it), **Also reads** (older key names), **CLI override**, then a description. `auto_update_config` rebuilds the file from the getters and writes it back. So the getter reads an older key name once, and the file is saved under the current name. **CLI override** means a command-line option takes precedence for that run (`merged_settings` in `ofscraper/utils/settings.py`).

### Contents

* [Top level](#top-level)
* [`file_options`](#file_options)
* [`download_options`](#download_options)
* [`binary_options`](#binary_options)
* [`cdm_options`](#cdm_options)
* [`performance_options`](#performance_options)
* [`content_filter_options`](#content_filter_options)
* [`advanced_options`](#advanced_options)
* [`script_options`](#script_options)
* [`responsetype`](#responsetype)

### Top level

#### `main_profile`

* **Default:** `"main_profile"` · **Read by:** `get_main_profile()` in `ofscraper/utils/config/data.py`
* **Default from:** [`PROFILE_DEFAULT`](/ofsc/reference/env.md#profile_default), [`mainProfile`](/ofsc/reference/env.md#mainprofile)
* The name of the profile folder in the config directory. The folder holds `auth.json`, the cache and (by default) the per-creator databases. The name also appears in log file names. The `--profile` option overrides it for one run.

#### `metadata`

* **Default:** `"{configpath}/{profile}/.data/{model_id}"` · **Read by:** `get_metadata()` in `ofscraper/utils/config/data.py`
* **Default from:** [`METADATA_DEFAULT`](/ofsc/reference/env.md#metadata_default)
* The folder pattern for each creator's `user_data.db`. It uses placeholders such as `{configpath}`, `{profile}`, `{model_id}` and `{model_username}`. On Fansly runs a site subfolder is appended unless the pattern already contains a site-specific placeholder, so the two sites never share a database.

#### `discord`

* **Default:** `""` · **Read by:** `get_discord()` in `ofscraper/utils/config/data.py`
* **Default from:** [`DISCORD_DEFAULT`](/ofsc/reference/env.md#discord_default)
* **CLI override:** `--discord`
* The Discord webhook URL that log messages are posted to. Nothing is sent unless the run's Discord log level is raised with `-dc`/`--discord` set to `LOW` or `NORMAL`. The option defaults to `OFF`.

### `file_options`

#### `file_options.save_location`

* **Default:** `"{home_directory}/Data/ofscraper"` · **Read by:** `get_save_location()` in `ofscraper/utils/paths/common.py`
* **Default from:** [`SAVE_PATH_DEFAULT`](/ofsc/reference/env.md#save_path_default)
* The root folder for downloads. `dir_format` is resolved under it. It is also the temp-file root when `temp_dir` is unset. Fansly runs save to a `Fansly` subfolder of it. Surrounding quotes from the Windows "Copy as path" command are stripped.

#### `file_options.dir_format`

* **Default:** `"{model_username}/{responsetype}/{mediatype}/"` · **Read by:** `get_dirformat()` in `ofscraper/utils/config/data.py`
* **Default from:** [`DIR_FORMAT_DEFAULT`](/ofsc/reference/env.md#dir_format_default)
* The folder pattern for each downloaded file, relative to `save_location`. It is built from placeholders such as `{model_username}`, `{responsetype}` and `{mediatype}`. It is ignored for a file when `naming_script` returns a path.

#### `file_options.file_format`

* **Default:** `"{filename}.{ext}"` · **Read by:** `get_fileformat()` in `ofscraper/utils/config/data.py`
* **Default from:** [`FILE_FORMAT_DEFAULT`](/ofsc/reference/env.md#file_format_default)
* The file name pattern for each download. It is built from placeholders such as `{filename}`, `{ext}`, `{date}`, `{text}` and `{media_id}`. It is ignored for a file when `naming_script` returns a path.

#### `file_options.textlength`

* **Default:** `0` · **Read by:** `get_textlength()` in `ofscraper/utils/config/data.py`
* **Default from:** [`TEXTLENGTH_DEFAULT`](/ofsc/reference/env.md#textlength_default)
* **CLI override:** `--textlength`
* The maximum length of post text used in names (the `{text}` placeholder and text-based file names). It is counted in letters or words, according to `text_type_default`. 0 means no limit. The `-tl`/`--textlength` option overrides it.

#### `file_options.space_replacer`

* **Default:** `" "` · **Read by:** `get_spacereplacer()` in `ofscraper/utils/config/data.py`
* **Default from:** [`SPACE_REPLACER_DEFAULT`](/ofsc/reference/env.md#space_replacer_default)
* **Also reads:** `space-replacer`
* **CLI override:** `--space-replacer`
* The character that replaces spaces in post text used for file and folder names. In word mode it also serves as the word separator. An empty value falls back to a space. The `-sr`/`--space-replacer` option overrides it.

#### `file_options.date`

* **Default:** `"MM-DD-YYYY"` · **Read by:** `get_date()` in `ofscraper/utils/config/data.py`
* **Default from:** [`DATE_DEFAULT`](/ofsc/reference/env.md#date_default)
* An arrow date-format string (for example `MM-DD-YYYY`). It formats the `{date}` placeholder in `dir_format`, `file_format` and naming-script payloads.

#### `file_options.text_type_default`

* **Default:** `"letter"` · **Read by:** `get_textType()` in `ofscraper/utils/config/data.py`
* **Default from:** [`TEXT_TYPE_DEFAULT`](/ofsc/reference/env.md#text_type_default)
* **CLI override:** `--text-type`
* Whether `textlength` counts `letter`s or `word`s. Any other value falls back to the default. The `-tt`/`--text-type` option overrides it.

#### `file_options.truncation_default`

* **Default:** `true` · **Read by:** `get_truncation()` in `ofscraper/utils/config/data.py`
* **Default from:** [`TRUNCATION_DEFAULT`](/ofsc/reference/env.md#truncation_default)
* **CLI override:** `--original`
* When true, final file paths longer than the operating system's limit are shortened to fit. The `-g`/`--original` flag turns truncation off for one run.

#### `file_options.filename_collision`

* **Default:** `"media_id"` · **Read by:** `get_filename_collision()` in `ofscraper/utils/config/data.py`
* **Default from:** [`FILENAME_COLLISION_DEFAULT`](/ofsc/reference/env.md#filename_collision_default)
* What happens when a download's target path already holds a different file. `overwrite` keeps the old behaviour: the larger file wins. Any other value saves the new file as `name_<media_id>`, then `name_<media_id>_2` and so on. An existing file with identical content is kept.

### `download_options`

#### `download_options.filter`

* **Default:** `["Images", "Audios", "Videos"]` · **Read by:** `get_filter()` in `ofscraper/utils/config/data.py`
* **Default from:** [`FILTER_DEFAULT`](/ofsc/reference/env.md#filter_default)
* **Also reads:** `content_filter_options`
* **CLI override:** `--mediatype`
* The media types to process: a list or comma-separated string of Images, Audios and Videos (case-insensitive). An empty list processes all types. The `-mt`/`--mediatype` option overrides it.

#### `download_options.auto_resume`

* **Default:** `true` · **Read by:** `get_part_file_clean()` in `ofscraper/utils/config/data.py`
* **Default from:** [`RESUME_DEFAULT`](/ofsc/reference/env.md#resume_default)
* **Also reads:** `partfileclean`
* **CLI override:** `--no-auto-resume`
* When true, a leftover `.part` file is resumed with an HTTP range request. When false, partial files are deleted and downloads restart. The `-ar`/`--no-auto-resume` flag forces it off for one run.

#### `download_options.system_free_min`

* **Default:** `0` · **Read by:** `get_system_freesize()` in `ofscraper/utils/config/data.py`
* **Default from:** [`SYSTEM_FREEMIN_DEFAULT`](/ofsc/reference/env.md#system_freemin_default)
* **CLI override:** `system_free_min`
* The minimum free disk space. Once free space drops below it, scraping of further post areas stops with the message "Space min has been reached". It accepts bytes or a size string such as `10GB`. 0 disables the check. Space is measured on `OFSC_DISK_SPACE_CHECK_PATH` (default `/`), not on `save_location`. There is no CLI option for it.

#### `download_options.max_post_count`

* **Default:** `0` · **Read by:** `get_max_post_count()` in `ofscraper/utils/config/data.py`
* **Default from:** [`MAX_COUNT_DEFAULT`](/ofsc/reference/env.md#max_count_default)
* **CLI override:** `--max-post-count`
* The most media items (not posts) to download or process per creator, after all other filters. 0 means no cap. The `-xc`/`--max-post-count` and `-mxc`/`--max-media-count` options both override it, and they set the same value.

#### `download_options.verify_all_integrity`

* **Default:** `false` · **Read by:** `get_verify_all_integrity()` in `ofscraper/utils/config/data.py`
* **Default from:** [`VERIFY_ALL_INTEGRITY`](/ofsc/reference/env.md#verify_all_integrity)
* When true, `ffprobe` checks ordinary (non-DRM) video and audio downloads and Fansly streams against the expected duration. A truncated file is deleted and reported as failed. It requires `ffprobe`. There is no CLI option for it.

### `binary_options`

#### `binary_options.ffmpeg`

* **Default:** `""` · **Read by:** `get_ffmpeg()` in `ofscraper/utils/config/data.py`
* **Default from:** [`FFMPEG_DEFAULT`](/ofsc/reference/env.md#ffmpeg_default)
* The path to the ffmpeg executable. It is needed for DRM decryption and merging and for Fansly streams (version 6 or newer for DRM). If the path is empty or invalid, the app tries `OFSC_FFMPEG_DEFAULT`, then the pyffmpeg bundle, then `PATH`. Surrounding quotes are stripped.

### `cdm_options`

#### `cdm_options.private-key`

* **Default:** `null` · **Read by:** `get_private_key()` in `ofscraper/utils/config/data.py`
* **CLI override:** `--private-key`
* The path to the Widevine CDM private key file (`private_key.pem`). It is read when key-mode is `manual`. The `-pk`/`--private-key` option overrides it. Surrounding quotes are stripped.

#### `cdm_options.client-id`

* **Default:** `null` · **Read by:** `get_client_id()` in `ofscraper/utils/config/data.py`
* **CLI override:** `--client-id`
* The path to the Widevine CDM client ID blob (`client_id.bin`). It is read when key-mode is `manual`. The `-ci`/`--client-id` option overrides it. Surrounding quotes are stripped.

#### `cdm_options.key-mode-default`

* **Default:** `"cdrm"` · **Read by:** `get_key_mode()` in `ofscraper/utils/config/data.py`
* **Default from:** [`KEY_DEFAULT`](/ofsc/reference/env.md#key_default), [`KEY_OPTIONS`](/ofsc/reference/env.md#key_options)
* **CLI override:** `--key-mode`
* How DRM content keys are obtained. `manual` uses the local CDM files in `private-key` and `client-id`. `cdrm` asks cdrm-project.com and sends it the request headers, cookies included. Other values fall back to the default. The `-k`/`--key-mode` option overrides it.

### `performance_options`

#### `performance_options.download_sems`

* **Default:** `6` · **Read by:** `get_download_semaphores()` in `ofscraper/utils/config/data.py`
* **Default from:** [`DOWNLOAD_SEM_DEFAULT`](/ofsc/reference/env.md#download_sem_default)
* **CLI override:** `--downloadsem`
* The number of downloads that run at the same time. The worker thread pool is twice this size. It must be at least 1, and 0 or a negative number falls back to the default. The `--sem`/`-sd` option overrides it.

#### `performance_options.download_limit`

* **Default:** `0` · **Read by:** `get_download_limit()` in `ofscraper/utils/config/data.py`
* **Default from:** [`DOWNLOAD_LIMIT_DEFAULT`](/ofsc/reference/env.md#download_limit_default)
* **CLI override:** `--download-limit`
* The maximum download speed in bytes per second, shared across downloads. It accepts a size string such as `10MB`. 0 means unlimited, and any non-zero value below 1024 is raised to 1024. The `-dl`/`--download-limit` option overrides it.

### `content_filter_options`

#### `content_filter_options.block_ads`

* **Default:** `false` · **Read by:** `get_block_ads()` in `ofscraper/utils/config/data.py`
* **Default from:** [`BLOCKED_ADS_DEFAULT`](/ofsc/reference/env.md#blocked_ads_default)
* When true, posts whose text matches a built-in advertising regex (#ad, giveaway, shoutout, promo and similar) are excluded. This is added on top of any `--neg-filter` patterns. The `-ba`/`--block-ads` flag turns it on for one run.

#### `content_filter_options.file_size_max`

* **Default:** `0` · **Read by:** `get_filesize_max()` in `ofscraper/utils/config/data.py`
* **Default from:** [`FILE_SIZE_MAX_DEFAULT`](/ofsc/reference/env.md#file_size_max_default)
* **Also reads:** `download_options`, `file_size_limit`
* **CLI override:** `--size-max`
* Media larger than this are skipped at download time. The `db` command and the table view also apply it. It accepts bytes or a size string such as `500MB`. 0 means no limit, and an unparseable value is treated as 0. The `-sx`/`--size-max` option overrides it.

#### `content_filter_options.file_size_min`

* **Default:** `0` · **Read by:** `get_filesize_min()` in `ofscraper/utils/config/data.py`
* **Default from:** [`FILE_SIZE_MIN_DEFAULT`](/ofsc/reference/env.md#file_size_min_default)
* **Also reads:** `download_options`
* **CLI override:** `--size-min`
* Media smaller than this are skipped at download time. The `db` command and the table view also apply it. It accepts bytes or a size string. 0 means no limit, and an unparseable value is treated as 0. The `-sm`/`--size-min` option overrides it.

#### `content_filter_options.length_max`

* **Default:** `0` · **Read by:** `get_max_length()` in `ofscraper/utils/config/data.py`
* **Default from:** [`MAX_LENGTH_DEFAULT`](/ofsc/reference/env.md#max_length_default)
* **Also reads:** `download_options`
* **CLI override:** `--length-max`
* The maximum duration in seconds. Longer videos are filtered out. Only videos with a known duration are affected, not audio or images. 0 means no limit. The `-lx`/`--length-max` option overrides it.

#### `content_filter_options.length_min`

* **Default:** `0` · **Read by:** `get_min_length()` in `ofscraper/utils/config/data.py`
* **Default from:** [`MIN_LENGTH_DEFAULT`](/ofsc/reference/env.md#min_length_default)
* **Also reads:** `download_options`
* **CLI override:** `--length-min`
* The minimum duration in seconds. Shorter videos are filtered out. Only videos with a known duration are affected, not audio or images. 0 means no limit. The `-lm`/`--length-min` option overrides it.

### `advanced_options`

#### `advanced_options.dynamic-mode-default`

* **Default:** `"digital"` · **Read by:** `get_dynamic()` in `ofscraper/utils/config/data.py`
* **Default from:** [`DYNAMIC_OPTIONS_ALL`](/ofsc/reference/env.md#dynamic_options_all), [`DYNAMIC_RULE_DEFAULT`](/ofsc/reference/env.md#dynamic_rule_default)
* **CLI override:** `--dynamic-rules`
* Which source of OnlyFans request-signing rules to use. The values are `datawhores`, `xagler`, `rafa`, `digitalcriminals` (aliases `dc`, `digital`, `digitals`, `digitalcriminal`; the config menu lists and saves it as `digital`), `generic` (needs `OFSC_DYNAMIC_GENERIC_URL`) and `manual` (needs `OFSC_DYNAMIC_RULE_MANUAL`). An unknown value falls back to the default and logs a warning. Anything that yields no rule falls back to `datawhores`. The `-dr`/`--dynamic-rules` option overrides it.

#### `advanced_options.skip_unavailable_content`

* **Default:** `true` · **Read by:** `get_skip_unavailable_content()` in `ofscraper/utils/config/data.py`
* **Default from:** [`SKIP_UNAVAILABLE_DEFAULT`](/ofsc/reference/env.md#skip_unavailable_default)
* When true, timeline, pinned, archived, stories and highlights are not scraped for creators whose subscription has expired. Profile, purchased content and messages are still scraped. Labels and streams are scraped only for active subscriptions, whatever this setting says.

#### `advanced_options.downloadbars`

* **Default:** `false` · **Read by:** `get_show_downloadprogress()` in `ofscraper/utils/config/data.py`
* **Default from:** [`PROGRESS_DEFAULT`](/ofsc/reference/env.md#progress_default)
* **CLI override:** `--downloadbars`
* When true, the app shows a progress bar for each file being downloaded, in addition to the overall progress. The `-db`/`--downloadbars` flag can turn it on but not off.

#### `advanced_options.cache-mode`

* **Default:** `"sqlite"` · **Read by:** `cache_mode_helper()` in `ofscraper/utils/config/data.py`
* **Default from:** [`CACHEDEFAULT`](/ofsc/reference/env.md#cachedefault)
* The storage backend for the on-disk cache. `sqlite` stores pickled values in the `cache_sql` folder. `json` stores JSON values in the `cache_json` folder. `disabled` turns off the cache, the API cache and incremental downloads, like `--no-cache`. `api_disabled` turns off only the API response cache, like `--no-api-cache`, and keeps sqlite storage. Other values fall back to the default.

#### `advanced_options.rotate_logs`

* **Default:** `true` · **Read by:** `get_rotate_logs()` in `ofscraper/utils/config/data.py`
* **Default from:** [`ROTATE_DEFAULT`](/ofsc/reference/env.md#rotate_default)
* When true, each run writes its own log file in a per-day folder under the logging directory. When false, all runs of a day append to one file. It must be true for `logs_expire_time` to delete old logs.

#### `advanced_options.sanitize_text`

* **Default:** `false` · **Read by:** `get_sanitizeDB()` in `ofscraper/utils/config/data.py`
* **Default from:** [`SANITIZE_DB_DEFAULT`](/ofsc/reference/env.md#sanitize_db_default)
* When true, post and message text is stored in the database with HTML tags removed and whitespace collapsed. When false, the raw API text is stored. It does not affect file names.

#### `advanced_options.temp_dir`

* **Default:** `null` · **Read by:** `get_TempDir()` in `ofscraper/utils/config/data.py`
* **Default from:** [`TEMP_FOLDER_DEFAULT`](/ofsc/reference/env.md#temp_folder_default)
* The root folder for in-progress (`.part`) downloads. It is laid out with `dir_format`, like the final location. When unset, temp files are written under `save_location`. Surrounding quotes are stripped.

#### `advanced_options.remove_hash_match`

* **Default:** `null` · **Read by:** `get_hash()` in `ofscraper/utils/config/data.py`
* **Default from:** [`HASHED_DEFAULT`](/ofsc/reference/env.md#hashed_default)
* `true` hashes every download and deletes later files whose hash matches an earlier one for the same creator and media type. `false` only records hashes. `null` skips hashing.

#### `advanced_options.infinite_loop_action_mode`

* **Default:** `false` · **Read by:** `get_InfiniteLoop()` in `ofscraper/utils/config/data.py`
* **Default from:** [`INFINITE_LOOP_DEFAULT`](/ofsc/reference/env.md#infinite_loop_default)
* When true, action mode (`--action`) asks after each run whether to continue, and offers another action instead of exiting.

#### `advanced_options.incremental_downloads`

* **Default:** `true` · **Read by:** `get_incremental_downloads()` in `ofscraper/utils/config/data.py`
* **Default from:** [`INCREMENTAL_DOWNLOADS_DEFAULT`](/ofsc/reference/env.md#incremental_downloads_default)
* **Also reads:** `enable_auto_after`
* When true and no `--after` is given, each area is scanned only from the newest previously scanned post, instead of from the start. Like and unlike actions and forced full scans still scan everything. `--no-cache` or cache-mode `disabled` turns it off for the run. The legacy key `advanced_options.enable_auto_after` is read when this key is missing.

#### `advanced_options.default_user_list`

* **Default:** `"main"` · **Read by:** `get_default_userlist()` in `ofscraper/utils/config/data.py`
* **Default from:** [`DEFAULT_USER_LIST`](/ofsc/reference/env.md#default_user_list)
* **CLI override:** `--user_list`
* The OnlyFans user lists to select creators from when `-ul`/`--user-list` is not given. It is a list or a comma-separated string. The reserved names `ofscraper.main`, `ofscraper.active` and `ofscraper.expired` mean all, active and expired subscriptions. Names are matched case-insensitively.

#### `advanced_options.default_black_list`

* **Default:** `[]` · **Read by:** `get_default_blacklist()` in `ofscraper/utils/config/data.py`
* **Default from:** [`DEFAULT_BLACK_LIST`](/ofsc/reference/env.md#default_black_list)
* **CLI override:** `--black_list`
* The OnlyFans user lists whose members are excluded from selection when `-bl`/`--black-list` is not given. It is a list or a comma-separated string. Names are matched case-insensitively.

#### `advanced_options.logs_expire_time`

* **Default:** `0` · **Read by:** `get_logs_expire()` in `ofscraper/utils/config/data.py`
* The age in hours after which `.log` files in the logging directory are deleted at cleanup, along with empty log folders. 0 disables it. Nothing is deleted unless `rotate_logs` is true.

#### `advanced_options.ssl_verify`

* **Default:** `"custom"` · **Read by:** `get_ssl_verify()` in `ofscraper/utils/config/data.py`
* **Default from:** [`SSL_VALIDATION_DEFAULT`](/ofsc/reference/env.md#ssl_validation_default)
* The TLS mode for HTTP sessions. `false` (also `0`, `none` or empty) turns certificate verification off. `default` uses Python's standard SSL context. Any other value (normally `custom`) uses the hardened custom context in `cert.py`, which shapes the TLS fingerprint. A legacy JSON boolean (`true` or `false`) is read as `custom`.

#### `advanced_options.env_files`

* **Default:** `[]` · **Read by:** `get_env_files()` in `ofscraper/utils/config/data.py`
* **Also reads:** `script_options`, `scripts`
* A list of `.env`, `.yaml`/`.yml` or `.json` files whose values are loaded as environment variables (`OFSC_*` overrides) before settings are built. Later files override earlier ones. Before them, the app loads a `.env` file found by python-dotenv. It searches upward from `ofscraper/utils/of_env/`, and from the working folder only in the standalone binaries, the REPL or a debugger. The `--env-files` option replaces this list for one run.

### `script_options`

#### `script_options.after_action_script`

* **Default:** `null` · **Read by:** `get_after_action_script()` in `ofscraper/utils/config/data.py`
* **Default from:** [`AFTER_ACTION_SCRIPT_DEFAULT`](/ofsc/reference/env.md#after_action_script_default)
* **Also reads:** `advanced_options`
* **CLI override:** `--after-action-script`
* An executable that runs after each user is processed by the like, unlike or download actions. It also runs after scrape-paid, check and manual downloads. It receives JSON with the username, media and posts on stdin. The `-aas`/`--after-action-script` option overrides it.

#### `script_options.post_script`

* **Default:** `null` · **Read by:** `get_post_script()` in `ofscraper/utils/config/data.py`
* **Default from:** [`POST_SCRIPT_DEFAULT`](/ofsc/reference/env.md#post_script_default)
* **Also reads:** `advanced_options`, `scripts`
* **CLI override:** `--post-script`
* An executable that runs once when the program finishes. It receives JSON on stdin that lists processed and unprocessed users for the like, unlike, download and scrape-paid activities. The `-ps`/`--post-script` option overrides it.

#### `script_options.naming_script`

* **Default:** `null` · **Read by:** `get_naming_script()` in `ofscraper/utils/config/data.py`
* **Default from:** [`NAMING_SCRIPT_DEFAULT`](/ofsc/reference/env.md#naming_script_default)
* **Also reads:** `advanced_options`, `scripts`
* **CLI override:** `--naming-script`
* An executable that runs for each download to choose its path. It receives JSON about the media, post and current formats on stdin. Non-empty stdout is used as the full file path, in place of `dir_format` and `file_format`. Programs the script starts are stopped once it exits, times out or is cancelled, and when ofscraper exits (a warning is logged when the script exits and leaves any running). `nohup` and `&` don't keep a program running. On Linux and macOS, a program started in its own session (for example with `setsid`) is left running; on Windows, none is. The `-ns`/`--naming-script` option overrides it.

#### `script_options.after_download_script`

* **Default:** `null` · **Read by:** `get_after_download_script()` in `ofscraper/utils/config/data.py`
* **Default from:** [`AFTER_DOWNLOAD_SCRIPT_DEFAULT`](/ofsc/reference/env.md#after_download_script_default)
* **Also reads:** `advanced_options`, `scripts`
* **CLI override:** `--after-download-script`
* An executable that runs after each file is downloaded (text files included). It receives the final file path on stdin. Programs the script starts are stopped once it exits, times out or is cancelled, and when ofscraper exits (a warning is logged when the script exits and leaves any running). `nohup` and `&` don't keep a program running. On Linux and macOS, a program started in its own session (for example with `setsid`) is left running; on Windows, none is. The `-adl`/`--after-download-script` option overrides it.

#### `script_options.skip_download_script`

* **Default:** `null` · **Read by:** `get_skip_download_script()` in `ofscraper/utils/config/data.py`
* **Default from:** [`SKIP_DOWNLOAD_SCRIPT_DEFAULT`](/ofsc/reference/env.md#skip_download_script_default)
* **Also reads:** `advanced_options`, `scripts`
* **CLI override:** `--skip-download-script`
* An executable that runs before each download. It receives JSON about the media, post and total size on stdin. It's asked once per file (per track for a DRM video) per run. If it prints `false` or nothing, the file is skipped in this run only: it's counted as skipped, not saved as downloaded, and the script is asked about it again on the next run. If it prints `skip-permanent` (any case), the file is skipped for good: counted as skipped and saved as downloaded with no file, so it isn't asked about again. To undo that, run with `--retry-permanent-skips`, or un-mark the files with `ofscraper db --unmark-permanent-skips`. Any other output, or a script that fails, lets the download proceed. Until #351, `false` and nothing also saved the file as downloaded; to keep that, print `skip-permanent`. Programs the script starts are stopped once it exits, times out or is cancelled, and when ofscraper exits (a warning is logged when the script exits and leaves any running). `nohup` and `&` don't keep a program running. On Linux and macOS, a program started in its own session (for example with `setsid`) is left running; on Windows, none is. The `-sdl`/`--skip-download-script` option overrides it.

### `responsetype`

These values are the folder names that fill `{responsetype}` in `dir_format`. For each post, the app lowercases the post's own type, looks it up here, and capitalises the result with `str.capitalize()` (`Post.modified_responsetype` in `ofscraper/classes/of/posts.py`). Only the first letter stays uppercase. An empty or missing entry falls back to the type's own name. Archived posts always use `responsetype.archived`.

#### `responsetype.timeline`

* **Default:** `"Posts"` · **Read by:** `get_timeline_responsetype()` in `ofscraper/utils/config/data.py`
* **Default from:** [`RESPONSE_TYPE_DEFAULT`](/ofsc/reference/env.md#response_type_default)
* **Also reads:** `post`
* The folder name used for `{responsetype}` for timeline posts. The value is capitalised, so only its first letter stays uppercase. An empty value falls back to the type name.

#### `responsetype.message`

* **Default:** `"Messages"` · **Read by:** `get_messages_progress_responsetype()` in `ofscraper/utils/config/data.py`
* **Default from:** [`RESPONSE_TYPE_DEFAULT`](/ofsc/reference/env.md#response_type_default)
* The folder name used for `{responsetype}` for messages. The value is capitalised, so only its first letter stays uppercase. An empty value falls back to the type name.

#### `responsetype.archived`

* **Default:** `"Archived"` · **Read by:** `get_archived_responsetype()` in `ofscraper/utils/config/data.py`
* **Default from:** [`RESPONSE_TYPE_DEFAULT`](/ofsc/reference/env.md#response_type_default)
* The folder name used for `{responsetype}` for archived posts. It takes precedence over pinned and other types. The value is capitalised, so only its first letter stays uppercase. An empty value falls back to the type name.

#### `responsetype.paid`

* **Default:** `"Messages"` · **Read by:** `get_paid_responsetype()` in `ofscraper/utils/config/data.py`
* **Default from:** [`RESPONSE_TYPE_DEFAULT`](/ofsc/reference/env.md#response_type_default)
* The folder name used for `{responsetype}` for purchased (paid) content found by `--scrape-paid` or the purchased area. The value is capitalised, so only its first letter stays uppercase. An empty value falls back to the type name.

#### `responsetype.stories`

* **Default:** `"Stories"` · **Read by:** `get_stories_responsetype()` in `ofscraper/utils/config/data.py`
* **Default from:** [`RESPONSE_TYPE_DEFAULT`](/ofsc/reference/env.md#response_type_default)
* The folder name used for `{responsetype}` for stories. The value is capitalised, so only its first letter stays uppercase. An empty value falls back to the type name.

#### `responsetype.highlights`

* **Default:** `"Stories"` · **Read by:** `get_highlights_responsetype()` in `ofscraper/utils/config/data.py`
* **Default from:** [`RESPONSE_TYPE_DEFAULT`](/ofsc/reference/env.md#response_type_default)
* The folder name used for `{responsetype}` for story highlights. The value is capitalised, so only its first letter stays uppercase. An empty value falls back to the type name.

#### `responsetype.profile`

* **Default:** `"Profile"` · **Read by:** `get_profile_responsetype()` in `ofscraper/utils/config/data.py`
* **Default from:** [`RESPONSE_TYPE_DEFAULT`](/ofsc/reference/env.md#response_type_default)
* The folder name used for `{responsetype}` for profile media (avatar and header images). The value is capitalised, so only its first letter stays uppercase. An empty value falls back to the type name.

#### `responsetype.pinned`

* **Default:** `"Posts"` · **Read by:** `get_pinned_responsetype()` in `ofscraper/utils/config/data.py`
* **Default from:** [`RESPONSE_TYPE_DEFAULT`](/ofsc/reference/env.md#response_type_default)
* The folder name used for `{responsetype}` for pinned posts. The value is capitalised, so only its first letter stays uppercase. An empty value falls back to the type name.

#### `responsetype.streams`

* **Default:** `"Streams"` · **Read by:** `get_streams_responsetype()` in `ofscraper/utils/config/data.py`
* **Default from:** [`RESPONSE_TYPE_DEFAULT`](/ofsc/reference/env.md#response_type_default)
* The folder name used for `{responsetype}` for streams. The value is capitalised, so only its first letter stays uppercase. An empty value falls back to the type name.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://cloakedkeys.gitbook.io/ofsc/reference/config.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
