@javagt/tvnz-plus-api
v1.0.0
Published
TypeScript client for the TVNZ Plus streaming API. Ported by DeepSeek V4 Flash.
Readme
@javagt/tvnz-plus-api
Version 1.0.0 — TypeScript client for the TVNZ Plus streaming API.
Reverse-engineered from HAR captures of the official TVNZ Plus web application. Ported by DeepSeek V4 Flash.
Installation
npm install @javagt/tvnz-plus-apiLibrary Usage
Quick start with existing session
import { TvnzClient } from '@javagt/tvnz-plus-api';
const client = new TvnzClient();
// Load existing session from ozistream/ozivine local_storage.json
client.loadSession('/path/to/local_storage.json');
// Or inject tokens directly
client.setSession({
accessToken: 'eyJ...',
refreshToken: 'DASj...',
deviceref: '51ff1fd0-...',
});
// Get series details
const series = await client.series.getBySlug('shortland-street');
console.log(series?.displayInfo.title);
// Get seasons and episodes
const seasons = await client.series.getSeasons(series!.id);
const episodes = await client.series.getEpisodes(series!.id, seasons[0].id);Full auth flow (no session needed)
import { TvnzClient } from '@javagt/tvnz-plus-api';
const client = new TvnzClient();
await client.authenticate(); // OAuth2 → platform JWT → device registration
// Authorize video playback
const auth = await client.playback.authorize('shortland-street-81');
console.log('MPD:', auth?.mpdUrl);
console.log('License:', auth?.licenseUrl);Browse catalog
import { TvnzClient } from '@javagt/tvnz-plus-api';
const client = new TvnzClient();
client.loadSession('/path/to/local_storage.json');
// Homepage carousels
const homepage = await client.catalog.getHomepage();
// Continue watching
const watching = await client.catalog.getContinueWatching(userId, profileId);
// Recommendations
const recommended = await client.catalog.getRecommended(userId, profileId);Account management (Evergent API)
import { TvnzClient } from '@javagt/tvnz-plus-api';
const client = new TvnzClient();
// Browse subscription products
const products = await client.account.getProducts();
// Send OTP for login
await client.account.createOtp('[email protected]', 'recaptcha-token');
// Confirm OTP and get JWT
const result = await client.account.confirmOtp('[email protected]', '123456');
// Get entitlements
const entitlements = await client.account.getEntitlements(result!.contactId);ESM Imports
import { TvnzClient } from '@javagt/tvnz-plus-api';
import { TvnzAuth } from '@javagt/tvnz-plus-api';
import { CatalogApi, SeriesApi, PlaybackApi, AccountApi } from '@javagt/tvnz-plus-api';
import type { TvnzSession, Series, Episode, AuthorizeResponse } from '@javagt/tvnz-plus-api';API
TvnzClient
| Method | Description |
|--------|-------------|
| new TvnzClient(deviceId?) | Create client with optional device UUID |
| loadSession(path) | Load existing session from local_storage.json (ozistream/ozivine format) |
| setSession(session) | Inject session tokens directly |
| authenticate() | Full OAuth2 → platform JWT → device registration flow |
.catalog — CatalogApi
| Method | Description |
|--------|-------------|
| getHomepage() | Homepage carousels and recommendations |
| getContinueWatching(userId, profileId) | Continue-watching feed |
| getRecommended(userId, profileId) | Recommended content |
| getMoreLikeThis(seriesId) | "More Like This" recommendations |
| getLaunchConfig() | App launch configuration |
.series — SeriesApi
| Method | Description |
|--------|-------------|
| getBySlug(slug) | Series details by URL slug |
| getSeasons(seriesId) | Seasons for a series |
| getEpisodes(seriesId, seasonId) | Episodes for a season |
| getEpisode(slug) | Episode details by URL slug |
| getUpNext(seriesId, seasonNum, epNum) | "Up Next" recommendation |
| search(query) | Search catalog |
.playback — PlaybackApi
| Method | Description |
|--------|-------------|
| authorize(slug) | Authorize content playback, returns MPD + license URLs |
| getBookmark(contentId) | Get resume point for an episode |
| saveBookmark(itemId, offset, seasonId, episodeId) | Save resume point |
| createStream() | Create streaming session |
| deleteStream() | Delete streaming session |
.account — AccountApi
| Method | Description |
|--------|-------------|
| getProducts() | Available subscription plans |
| searchAccount(email) | Look up account by email |
| createOtp(email, captchaToken) | Send OTP email |
| confirmOtp(email, otp) | Verify OTP, return JWT + contactId |
| getContact(contactId?) | Get user profile |
| getEntitlements(contactId) | Get subscriptions/entitlements |
| getFavorites() | List favorited content |
| isFavorited(contentId) | Check if content is favorited |
Session Compatibility
This library uses the same session format as ozistream, ozivine (@javagt/ozivine), and other TVNZ download tools. The session file (local_storage.json) contains:
{
"accessToken": "eyJ...",
"refreshToken": "DASj...",
"deviceref": "51ff1fd0-..."
}To use an existing session export:
import { TvnzClient } from '@javagt/tvnz-plus-api';
const client = new TvnzClient();
client.loadSession('/path/to/local_storage.json');
await client.authenticate(); // auto-refreshes if neededOr inject tokens programmatically:
client.setSession({
accessToken: 'eyJ...',
refreshToken: 'DASj...',
deviceref: '51ff1fd0-...',
});License
MIT
Ported from TVNZ Plus web app HAR captures by DeepSeek V4 Flash.
