Skip to main content

Smart RSS Rules

Level: 🟣 Advanced · Time: ~60 minutes

Most people write RSS rules as a wall of regex, get flooded with duplicates, and give up. UltraTorrent's rules are built differently: you express preference, not pattern-matching, and the engine handles the rest.

Overview​

The mental shift: regex decides what is eligible. Preferences decide what you get.

Purpose​

To build a rule that:

  • Grabs exactly one release per movie or episode.
  • Picks the best available one, not the first one.
  • Upgrades itself when something genuinely better shows up.
  • Never grabs the same thing twice, even across feeds, re-posts and rotated GUIDs.
  • Can be tested before it ever downloads anything.

When to use this tutorial​

Use it when…Use something else when…
You want quality preferences applied consistently.You want to find gaps in a series β†’ Automating TV shows.
Your rules are grabbing duplicates.You want to search on demand β†’ Multiple indexers.
You want automatic quality upgrades.You are still getting a first download working β†’ Quick Start.

Prerequisites​

  • A working install with an engine (Quick Start).
  • A library whose root will contain your rule's save path β€” otherwise nothing gets organised.
  • Permissions: rss.view, rss.manage.
  • An RSS feed URL you actually want to watch.
  • Read Core Concepts β†’ Acquisition first. This tutorial builds directly on it.

Concepts​

TermMeaning
FeedA polled URL. The rss_poll job runs every 60 s and fetches feeds whose refresh interval has elapsed.
RuleLives under a feed. Include/exclude regex, media type, category, save path, auto-download.
Match candidateOne entry in the rule's ranked preference list.
Release identitymovie:<title>:<year> or ep:<title>:<season>:<episode> β€” the key level-3 dedup works on.
Info hash (btih)The torrent's identity, parsed out of the magnet. Level-2 dedup.
RssAcquisitionThe record of "this rule currently holds this release for that logical title".

Step-by-step​

Step 1 β€” Add the feed​

RSS & Acquisition β†’ RSS Feeds (/rss) β†’ Add feed.

FieldValue
NameYours
URLThe feed URL
Refresh intervalHow often to poll it
Enabledon

Expected result: the feed appears and, after the next rss_poll tick (within 60 seconds of its interval elapsing), begins showing items.

The 60-second tick is not your refresh interval

rss_poll runs every 60 seconds and fetches only the feeds whose own refresh interval has elapsed. Setting a feed to 15 minutes does not make it poll every 60 seconds β€” it makes it poll every 15 minutes, checked every 60 seconds.

RSS feeds page with feeds and rules


Step 2 β€” Create the rule with auto-download OFF​

This is the safety move that everyone should make and almost nobody does.

Add rule under the feed:

FieldValueNotes
Namee.g. Dune Part TwoYours.
Media typemovie / tv / anime / …For tv/anime this activates show-status awareness.
Include regexWhat a candidate must matchKeep it broad.
Exclude regexWhat a candidate must not matchKeep it narrow.
Save path/downloads/moviesMust be inside a library's root, or nothing gets organised.
Auto-downloadOFF ← for nowThe rule records matches without grabbing them.

Save, and let it run for a poll cycle or two.

Expected result: the rule's match history shows what it would have grabbed β€” with nothing downloaded.

Auto-download OFF is also the "backfill rule" pattern

A rule with auto-download off keeps matching and recording forever without grabbing. That is exactly what the convert_rule_to_backfill automation action does when a show ends β€” it turns off autoDownload and keeps the rule.


Step 3 β€” Get the regex right (and keep it dumb)​

The most common mistake is trying to encode quality in the regex. Do not. That is what the preference list is for.

RegexShould expressShould not express
IncludeWhich title is this about?Which resolution / source / group you prefer.
ExcludeWhat is categorically unacceptable? (CAM, TS, a language you cannot read)Anything you would merely rather avoid.

A good include regex is broad enough to catch every release of the thing, and nothing else. A good exclude regex is a short list of things you would never take under any circumstances.

Expected result: the rule matches every release of your target, at every quality, and nothing unrelated.

An over-tight exclude will silently starve the rule

If you exclude everything except one exact release string, the rule will find that string or nothing at all β€” and you will never get an upgrade, because there is nothing better it is allowed to see. Let the preference list do the choosing.


Step 4 β€” Build the preference list​

Open the rule detail page (/rss/rules/:ruleId). This is where the Smart Match Builder and Match Preferences live, along with a testing panel and match history.

Build an ordered list of match candidates β€” best first:

1. 2160p Β· Remux Β· Dolby Vision Β· Atmos ← ideal
2. 2160p Β· WEB-DL Β· HDR10 Β· DD+ 5.1
3. 1080p Β· BluRay Β· SDR Β· DTS-HD
4. 1080p Β· WEB-DL Β· SDR Β· DD+ 5.1 ← perfectly fine
5. 720p Β· WEB-DL ← acceptable in a pinch
β€” (anything not on the list is not acceptable)

The list is ranked, and that ranking is what powers both the initial grab and every future upgrade.

Expected result: the Match Preferences list is ordered exactly the way you would choose by hand.

Smart Match Builder with a ranked preference list


Step 5 β€” Understand what the rule will now do​

This is the heart of the tutorial. Three levels of deduplication run on every candidate, in both live polling and backfill:

Level 3 is the one that changes how you think. A rule with a preference list holds exactly one release per logical title β€” movie:<title>:<year> or ep:<title>:<season>:<episode>. It grabs the best available so far, upgrades when something strictly higher-priority appears, and skips everything equal or worse.

An upgrade DELETES the superseded torrent and its data

This is intentional and it is the whole point: you asked for the best release, so holding two is pointless. But be aware:

  • The old torrent is removed from the engine.
  • Its data is deleted.
  • If you hardlinked it into a library, the library copy survives (that is what hardlinks are for) β€” but the seeding copy is gone.

If you never want this, do not rank a better release above the one you hold, or disable upgrades in the acquisition profile (duplicateRules.allowUpgrades).

If the title cannot be parsed, level 3 does not apply

Release identity is parsed from the name. An unparseable title falls back to plain per-release behavior β€” so a rule matching weirdly named releases may hold more than one. That is a graceful degradation, not a bug.


Step 6 β€” Test the rule before you arm it​

The rule detail page has a testing panel. Use it against real feed items and check that:

  • The right releases match.
  • The right ones are ranked highest.
  • The junk is excluded.

Then go further: paste a candidate release name into the Decision Simulator (/media-acquisition/simulator). It runs the entire acquisition pipeline β€” identify β†’ preferences β†’ score β†’ library comparison β†’ upgrade rules β€” and renders each stage as a clickable trace, with no side effects at all. Nothing is persisted, no action is taken, nothing is downloaded.

Expected result: you can predict, with confidence, what the rule will do to any given release.

Decision Simulator showing the explainable pipeline


Step 7 β€” Turn auto-download on​

Edit the rule and enable Auto-download.

Expected result: on the next poll, matching releases are grabbed β€” one per logical title, best available β€” and appear on /torrents.

Watch /rss and the rule's match history for the first cycle. You should see grabs, skips and (eventually) upgrades, each with a reason.


Step 8 β€” Tune the score thresholds​

Release Scoring gives every parsed release a 0–100 score plus an accept/reject decision with reasons and warnings. Your acquisition profile turns that score into behaviour:

Profile fieldEffect
minimumScoreBelow this β†’ skip.
approvalScoreBelow this β†’ hold_for_approval (a human decides).
qualityRules.waitForBetter + waitUntilScoreThe wait policy: a release that is β‰₯ minimum but < waitUntilScore becomes wait β€” deliberately held out on.
duplicateRules.allowUpgradesWhether upgrades are permitted at all.
automationRules.approvalRequiredForce approval for everything.

You can inspect and tune the scoring itself on Release Scoring (/release-scoring).

wait is a feature, not a stall

If nothing is downloading and the Waiting queue is full, the engine is doing exactly what you told it: the available releases are acceptable but not good enough, so it is holding out for something better. Lower waitUntilScore if you would rather have it now.

Expected result: the Smart Download dashboard's queues (Approved Β· Pending approval Β· Waiting Β· Pending upgrades Β· Rejected) reflect decisions you agree with.

Smart Download dashboard with decision queues


Step 9 β€” Understand what counts as an upgrade​

Upgrades are multi-dimensional, not resolution-only:

DimensionBest β†’ worst
Resolution2160p β†’ 1080p β†’ 720p β†’ 480p
SourceRemux β†’ BluRay β†’ WEB-DL β†’ WEBRip β†’ HDTV
HDRDolby Vision β†’ HDR10+ β†’ HDR10 β†’ HLG β†’ SDR
AudioAtmos / DTS:X β†’ TrueHD / DTS-HD β†’ DD+ β†’ DTS/DD β†’ AAC
Channels7.1 β†’ 5.1 β†’ 2.0

When a candidate wins, the winning dimensions surface in the decision reason β€” e.g. "owned, lower quality (resolution 2160p > 1080p, HDR Dolby Vision > SDR)".

Codec alone never triggers an upgrade

HEVC/AV1 vs AVC is a scoring tiebreak only. An x264 β†’ x265 re-encode at the same quality is not worth re-downloading, so it will never, on its own, cause an upgrade. This is deliberate, and it is the single most common source of "why won't it upgrade to the x265?" β€” the answer is: because that is not an upgrade.

Watch this tutorial

Video coming soon.


Examples​

A movie rule that behaves itself​

SettingValue
Media typemovie
Includebroad β€” matches the title
ExcludeCAM|HDTS|TELESYNC|HDCAM
Save path/downloads/movies (inside the Movies library root)
Auto-downloadon (after testing with it off)
Preferences2160p Remux DV β†’ 2160p WEB-DL HDR10 β†’ 1080p BluRay β†’ 1080p WEB-DL
ProfileallowUpgrades: true, sensible minimumScore

Result: it grabs the best it can find now, and quietly upgrades to the Remux when one appears β€” removing the old torrent and its data.

A rule that deliberately does not upgrade​

Same as above, but set duplicateRules.allowUpgrades: false in the profile. It grabs once, and never touches it again.

A backfill-only rule​

Auto-download off. It records every match forever and grabs nothing. Pair it with the watchlist + Missing Episodes flow for controlled acquisition.


Troubleshooting​

SymptomCauseFix
Rule matches nothingInclude regex too tight, or the feed has no matching items.Test in the rule's testing panel. Broaden the include.
Rule matches everythingInclude regex too loose.Tighten it β€” but keep quality out of it.
Duplicates keep arrivingThe releases have unparseable titles, so level-3 dedup falls back to per-release.Check that the release names parse to a release identity.
It grabbed then instantly deletedAn upgrade β€” a strictly higher-priority release appeared.Working as designed. Reorder your preference list if you disagree.
It will not upgrade to the x265Codec is a tiebreak only, never an upgrade dimension.This is intentional.
Nothing downloads; the Waiting queue is fullYour waitUntilScore is higher than anything available.Lower it, or wait.
Everything lands in Pending approvalapprovalRequired, or the score is below approvalScore.Adjust the profile, or approve.
Grabs succeed but nothing is organisedThe rule's save path is not inside an enabled library's root.Fix the save path.
"Torrent URL resolves to a blocked internal address"SSRF guard vs. a private-IP indexer.Add the host to SSRF_ALLOW_HOSTS (keep prowlarr).
A TV rule refuses to saveThe show is ended / canceled.Confirm the override (it is audited), or use a backfill rule.
The feed stopped updatingThe feed URL is dead or rate-limiting.Open the feed on /rss and check its status and history β€” a failing poll stops advancing the last-poll time and records the error.

Tips​

Always start with auto-download OFF

One poll cycle of "what would it have grabbed?" is worth an hour of cleanup.

Keep the regex dumb and the preferences smart

Regex answers "is this the right title?". Preferences answer "is this the right release?". Mixing them produces rules nobody can debug six months later.

The Decision Simulator has zero side effects β€” abuse it

Nothing is persisted, no action runs, nothing downloads. Paste in every weird release name you can find and read the trace.

Upgrades delete data

Read the danger box in Step 5 before you enable allowUpgrades on anything you care about.

One brain, two paths

Smart Download consumes the RSS module's Smart Match preference lists and the Release Scoring engine as the source of truth. It orchestrates; it does not duplicate. Tune quality once, and both RSS and missing-episode acquisition obey it.


FAQ​

Can one rule cover a whole TV show? Yes. Set media type tv, an include regex matching the show, and a preference list. Level-3 dedup keys on ep:<title>:<season>:<episode>, so it holds one release per episode.

What happens if two feeds carry the same release? Level-2 dedup catches it by info-hash. It is grabbed once.

Does a rotated GUID trick it? No β€” that is precisely what level 2 exists for.

Why did it skip a release that looks better to me? Read the reason. It will name the stage: an exclude term, a score below minimum, already owned at equal-or-better quality, or below the preference list entirely. The Decision Simulator will show you the whole trace.

Do RSS rules search indexers? No. RSS feeds are not indexers. RSS is polled and pushes items at your rules; indexers are searched on demand, over Torznab/Newznab, by the acquisition pipeline. Different subsystems.

How do I find out when a feed breaks? By looking: the feed's status and history on /rss record the failure, and its last-poll time stops advancing. Nothing pushes that to you.


Checklist​

Verification​

  • A feed exists and is polling.
  • A rule exists with a broad include and a narrow exclude.
  • Its save path is inside a library's root.
  • I ran it with auto-download OFF for at least one cycle and reviewed the matches.
  • A ranked Match Preferences list is built in the Smart Match Builder.
  • I tested candidate names in the Decision Simulator and understood every trace.
  • Auto-download is now on.
  • The rule holds exactly one release per logical title.
  • I know that an upgrade deletes the superseded torrent and its data.
  • I know that a codec change alone never upgrades.
  • The Smart Download queues (Waiting / Approvals / Upgrades / Rejected) look right.

Expected results​

ScreenExpected
/rssFeeds polling; rules matching
/rss/rules/:idA ranked preference list + a sensible match history
/media-acquisition/simulatorA full trace for any release you paste
/media-acquisition/dashboardQueues that reflect decisions you agree with
/torrentsOne release per title, upgraded when something better lands

Next steps​

  1. Multiple indexers β€” give the engine more to choose from.
  2. Automating TV shows β€” pair forward RSS with backward gap-filling.

See also​