Skip to content

Media Metadata

github-actions[bot] edited this page Aug 2, 2026 · 8 revisions

Media metadata

Load media through a reusable Client:

using var client = new Client("https://your-mirror.example");
using var media = await client.GetAsync(
    "/films/drama/123-title.html",
    cancellationToken);

Or load one absolute page directly:

using var media = await Media.CreateAsync(
    "https://your-mirror.example/films/drama/123-title.html",
    cancellationToken: cancellationToken);

Core properties

Console.WriteLine(media.Id);
Console.WriteLine(media.Url);
Console.WriteLine(media.Origin);
Console.WriteLine(media.Name);
Console.WriteLine(media.OriginalName);
Console.WriteLine(media.Description);
Console.WriteLine(media.ShortDescription);
Console.WriteLine(media.ReleaseYear);
Console.WriteLine(media.Thumbnail);
Console.WriteLine(media.ThumbnailHighQuality);
Console.WriteLine(media.Rating.Value);
Console.WriteLine(media.Rating.Votes);
Console.WriteLine(media.Format);
Console.WriteLine(media.Category);

Description contains the complete visible description. ShortDescription contains the shorter metadata summary and can be null when the website does not provide one separately. Loading both values does not require an additional request

Rating is the internal aggregate score submitted by HDRezka users, not an external service score. Rating.Value and Rating.Votes are nullable when the page has no recognizable rating. External scores remain available through Details.ExternalRatings. An external rating contains the HDRezka redirect in Url, the decoded external address in TargetUrl, and the source identifier in Id. IMDb identifiers retain the tt prefix, while Kinopoisk identifiers are numeric strings. Redirect decoding is local and does not send another request

An authenticated account can submit an integer score from 1 through 10:

var updated = await media.RateAsync(9, cancellationToken);
Console.WriteLine($"{updated.Value} ({updated.Votes})");

The method also updates media.Rating. The website can reject a repeated vote from the same account, which is reported as RatingException.

Names and OriginalNames preserve all parsed title variants, where Name is the first localized title, while OriginalName is the last original title or null

Alternative titles are separated only by a standalone slash surrounded by spaces. Slashes that belong to a title, including double slashes such as in .hack//Roots, remain part of the same title

MediaFormat describes the player shape:

  • Movie
  • Series
  • Unknown

MediaCategory is inferred from the catalog URL:

  • Film
  • Series
  • Cartoon
  • Anime
  • Show
  • Unknown

Format and category answer different questions; for example, an anime series has MediaFormat.Series and MediaCategory.Anime

Playback availability

A media page can keep its metadata after the website loses its player data or temporarily starts restoring it:

Console.WriteLine(media.Playback.IsAvailable);
Console.WriteLine(media.Playback.Availability);
Console.WriteLine(media.Playback.Reason);

PlaybackAvailability contains Available, TemporarilyUnavailable, and Unavailable. When playback is unavailable, translator collections are empty while the remaining media metadata and non-player operations stay accessible

Stream and episode operations throw PlaybackUnavailableException containing the same PlaybackState without sending a player request

Extended details

Details contains metadata that is already present in the downloaded media page and therefore requires no additional request:

Console.WriteLine(media.Details.Tagline);
Console.WriteLine(media.Details.ReleaseDate);
Console.WriteLine(media.Details.Quality);
Console.WriteLine(media.Details.AgeRating);
Console.WriteLine(media.Details.Duration);

foreach (var country in media.Details.Countries)
{
    Console.WriteLine(country.Name);
}

foreach (var person in media.Details.Cast)
{
    Console.WriteLine($"{person.Name}: {person.Url}");
}

The remaining collections expose genres, directors, linked collections, rankings, external ratings, recommendations, and series schedule entries. Nullable values indicate that the compatible website omitted the value or used an unrecognized format

Translations

foreach (var translator in media.TranslationOptions)
{
    Console.WriteLine(
        $"{translator.Id}: {translator.Name}; " +
        $"Premium={translator.IsPremium}; " +
        $"Camrip={translator.IsCamrip}; " +
        $"Ads={translator.HasAds}; " +
        $"DirectorCut={translator.IsDirectorCut}");
}

Use TranslationOptions when variants must remain distinct because compatible websites can return normal and director's-cut entries with the same numeric identifier

The compatibility views are:

  • Translators — the first entry for each numeric ID
  • TranslatorsByName — entries indexed by name without case sensitivity

Sort candidates using the configured priority:

var ordered = media.SortTranslators();

Or override priority for one operation:

var ordered = media.SortTranslators(
    preferred: [111, 56],
    nonPreferred: [238]);

See Configuration for persistent translator settings

Related parts

OtherParts contains related titles in website order:

foreach (var part in media.OtherParts)
{
    Console.WriteLine($"{part.Title}: {part.Url}");
}

Load linked pages as complete media objects with bounded concurrency:

var parts = await media.GetOtherPartsAsync(cancellationToken);
foreach (var part in parts)
{
    using (part)
    {
        Console.WriteLine(part.Name);
    }
}

Person pages

var reference = media.Details.Cast[0];
var person = await client.People.GetAsync(reference, cancellationToken);

Console.WriteLine(person.OriginalName);
Console.WriteLine(person.BirthDateLabel);
foreach (var career in person.Careers)
{
    Console.WriteLine($"{career.Name}: {career.Summary}");
}

Trailers and schedule state

var trailer = await media.GetTrailerAsync(cancellationToken);
Console.WriteLine(trailer.SourceUrl);

var scheduleEntry = media.Details.Schedule[0];
var watched = await media.SetScheduleWatchedAsync(
    scheduleEntry,
    isWatched: true,
    cancellationToken);

Account state attached to media

media.AccountTier and media.IsPremiumAccount describe the session used when the page was loaded; see Premium access before using these values to make authorization decisions

Comments

Comments are loaded separately through the website AJAX endpoint:

var page = await media.Comments.GetPageAsync(page: 1);

var created = await media.Comments.AddAsync(
    "A detailed review that follows the website rules",
    cancellationToken);
var reply = await media.Comments.ReplyAsync(
    created.Id,
    "A reply to the review",
    cancellationToken);
await media.Comments.DeleteAsync(reply.Id, cancellationToken);

CommentPage contains nested comments in website order, current and total page numbers, and the latest update identifier. Each comment exposes its parent identifier, nesting depth, author, avatar, date label, text, like count, and permalink. It also exposes the author profile, formatted HTML, current-account like state, and available deletion or report controls

var like = await media.Comments.ToggleLikeAsync(comment.Id, cancellationToken);
var users = await media.Comments.GetLikeUsersAsync(comment.Id, cancellationToken);
await media.Comments.ReportAsync(
    comment.Id,
    issueId: 2,
    description: "Spam links",
    cancellationToken);

Creation, replies, and deletion require an authenticated account and can be rejected by moderation, captcha, ownership checks, or comment rules. The live website exposes deletion for a user's own comments but does not expose comment editing, so the library intentionally has no edit method.

Clone this wiki locally