Twinby Subscription Prices, Ratings & RuStore Data
Pricing
from $5.00 / 1,000 storefront snapshots
Twinby Subscription Prices, Ratings & RuStore Data
Live Twinby subscription prices by country from the App Store, Google Play and RuStore, converted to USD, with ratings and change tracking between runs.
Pricing
from $5.00 / 1,000 storefront snapshots
Rating
0.0
(0)
Developer
Tim Zinin
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Twinby App Intel — Subscription Prices by Country, Rating and RuStore Read
Twinby's own Week/Month/3-month subscription prices, Boost and Super Like packs and Travel Mode price, read straight from Twinby's own App Store and Google Play listings for any country you name, plus an optional RuStore read for the same app — converted to USD where a rate exists, compared across storefronts, with the app's rating, version and release notes attached. No login, no API key, no profile data — only what Twinby itself already publishes.
Twinby prices its Week/Month/3-month plan in rubles for its home Russian market and in
dollars for its US storefront, with no fixed exchange rate connecting the two — a Месяц
subscription was 895,00 ₽ and a 1 month subscription was $29.99 at the time this README
was written, and the honest answer to "which is more expensive" depends on a currency market
this Actor will not silently guess at (see Pricing and Evidence and boundaries for exactly
why). This Actor reads both storefronts' own real numbers so you can apply whatever FX rate
your own use case actually trusts, rather than trusting a number nobody can audit.
What you get
- Twinby's own duration-named plan list, in whichever language that storefront uses.
inAppPurchases[]on an App Store row carries the exact list a paying subscriber sees on their phone in that country —Неделя,Месяц,3 месяца,1 буст,5 суперлайков,Режим путешествийin Russian, or1 week,1 month,Travel Modein English on other storefronts — in that storefront's own currency. None of it is inferred from a marketing page or translated by this Actor; each storefront's own language is passed through as-is. - planFamily collapses every duration and every language into one stable label. Twinby
does not name its subscription tiers the way Tinder or Bumble do ("Gold", "Premium") — its
own App Store feed names the SAME subscription by its duration instead:
Неделя(a week),Месяц(a month),3 месяца(three months) in Russian,1 week/1 month/3 monthsin English. All of these collapse to oneplanFamily: "Premium", withdurationDays(7, 30 or 90) carrying the length that the name itself states — so you can compare "the weekly plan's price" across every country in one filter, in either language, without writing your own regex over Cyrillic and Latin duration words.Boost(буст/boost, pluralбусты),SuperLike(суперлайк/superlike, pluralсуперлайки) andTravelMode(/Режим путешествийTravel Mode) are the three other real families this brand's own pages use; anything else is reported asplanFamily: "other"rather than forced into the nearest one. - A genuine three-storefront read, unique to this Actor's own line. Twinby is the only
brand in this line's five Actors that is also sold through RuStore
(
rustore.ru/catalog/app/com.twinby), the Russian alternative app store — setplatformsto include"rustore"and this Actor reads that listing too, for rating, install count, version and release notes (RuStore's own public page does not carry a priced IAP list the way the App Store's does, soinAppPurchases[]is always[]on arustorerow). This is explicitly an OPTIONAL platform, not part of the default prefill — see Evidence and boundaries for exactly why, and read it before you plan a production schedule around it. - USD conversion, honestly
nullfor the one currency that needs it most here. SetconvertToUsd(on by default) and every USD-priced entry gets itsusdfield filled in directly (amount == usdwhen the source currency already is USD). For a RUB-priced entry — every price on Twinby's own home Russian storefront —usdstaysnullandfxNotesays"no ECB rate for RUB", because the European Central Bank's own daily reference rate feed, the single FX source this Actor trusts, does not carry a RUB rate at all. This is arguably the single most important honesty guarantee for this specific brand: Twinby's largest storefront by rating count is priced in the one major currency this Actor cannot silently convert, and this README says so directly rather than quietly attaching a rate from some other, unaudited source. - Track price and rating changes over time, per storefront. Set
compareWithPreviousRuntotrueand give the run awatchId, and every row after the first for thatwatchIdcarries achanges[]array — new or removed plans, price moves, rating moves of 0.05 or more, version bumps — compared against the last time you ran that exactcountry/platformpair under thatwatchId. - Independent storefront reads, not a single global snapshot. Every
country × platformpair is fetched on its own — a RuStore antibot block does not affect the Russian App Store row in the same run, a rating change in the US does not touch the Russian numbers. You choose exactly which storefronts to check, from one country to sixty, across up to three platforms. - Runs on Apify: schedule it daily or weekly, call it from the REST API or an SDK, wire it to a webhook, or export straight to JSON, CSV or Excel — see Integration recipes below.
Who uses it
-
Competitive intelligence teams at Tinder, Bumble, Hinge, Badoo and every other dating app competing for the same Russian-speaking and CIS subscriber base. Twinby is a real, actively-rated competitor with tens of thousands of App Store ratings on its Russian storefront alone; a product team deciding how to price a new market entry wants this brand's real current numbers, not a guess based on an old screenshot someone on the team happened to take.
-
ASO and mobile-growth agencies serving clients in the Russian-speaking dating-app market, who already track ratings and review velocity for a portfolio of apps across App Store, Google Play and, where relevant, RuStore, and want Twinby's subscription pricing folded into the same report on the same schedule.
-
FX and pricing researchers studying RUB-denominated digital subscription pricing specifically — Twinby's RUB pricing, read directly off the storefront with no conversion applied by default, is a cleaner primary-source input than a converted number from a third party would be, precisely because this Actor states plainly when it does NOT have a trustworthy rate to convert with, rather than picking one.
-
Analysts tracking the RuStore alternative-app-store ecosystem — Russia's own domestic app store landscape (RuStore among them) is a distinct, less-documented market from the App Store/Google Play duopoly most tooling covers; this Actor's RuStore read is one of the very few automated, publicly-sourced feeds into that specific market for a real dating app.
-
Anyone comparing their own Twinby subscription cost between the Russian and US storefronts before deciding where to keep their billing region, using this Actor's own dataset rather than manually opening the App Store twice with the country setting changed.
-
Localization and market-entry consultants advising a Western dating app on whether and how to price a Russian-market or CIS-market launch use Twinby's real, live pricing ladder as one concrete comparable, rather than a generalized "Eastern European pricing is usually X% lower" assumption that may not hold for this specific vertical or this specific app.
This Actor does not serve anyone looking for Twinby user profiles, photos, messages, match data, or any other personal information about Twinby's own users — see "What this is NOT" under Evidence and boundaries.
How to run it
- Click Try for free — no card required, and the default input below runs without any secret or account of your own.
- Pick your Countries — ISO-3166 alpha-2 codes, lowercase. The default (
ru,us) contrasts Twinby's home market against its US storefront in one run — exactly the RUB-vs-USD comparison described above. - Pick your Platforms —
appstore,googleplay, orrustore(RuStore is available but NOT in the default prefill — add it explicitly if you specifically want that read, and read Evidence and boundaries first for the antibot risk that comes with it). - Leave Convert prices to USD on unless you only want each storefront's own local price.
- Press Start. The default two-country, two-platform input finishes in well under a
minute; adding
rustoreor a longer country list takes longer — see Operating guide. - Pull the results from the Dataset tab, or read the free run-level summary from the
Key-value store tab under the
OUTPUTkey.
Pricing
Pay-per-event, on the platform's standard PAY_PER_EVENT model: $0.005 charged once at
run start, plus $0.005 per storefront that came back with real data (status: "ok",
found: true — internally the platform's own event name for this is result-found; on the
page this is simply "a storefront with data"). Every other outcome is free: a country the app
is not sold in (not_available_in_country), a source that did not answer after this Actor's
own retries (rate_limited), a real parsing/source error including RuStore's antibot
challenge page (source_error), or an invalid country code (invalid_country). You are
billed only for a storefront that actually delivered a usable row.
The default prefill — two countries, two platforms (App Store and Google Play; RuStore is
NOT in the prefill), so up to four storefronts — resolves to $0.005 + up to 4 × $0.005 =
up to $0.025, and in this line's own testing Twinby has resolved successfully on every one
of those four combinations, so this is the figure to expect in practice. Adding rustore to
platforms adds one country-independent RuStore storefront at $0.005 if successful, but RuStore's own antibot behavior (Evidence and
boundaries) means a RuStore storefront may just as easily come back as a free
source_error — you are never charged for a RuStore attempt that the antibot blocked.
maxStorefronts (default 10, maximum 120) caps how many combinations one run will ever
attempt, enforced before any request is sent, with a free status: "truncated" row naming
exactly what was skipped.
At startup, the Actor checks that result events are configured as paid events and that ordinary dataset writes are free. It reads the event price once at startup. Before each successful storefront row, it uses that price snapshot and reads the remaining run budget from the Apify SDK. It does not compare the configured prices with the numbers printed on this page. The live Pricing tab is authoritative; set a maximum run charge to bound your spend.
Input contract
| Field | Required | What it does |
|---|---|---|
countries | no | ISO-3166 alpha-2 codes, lowercase, e.g. ["ru","us"]. 1 to 60 codes, deduplicated regardless of casing/whitespace. An invalid code comes back as a free invalid_country row; a valid code the app is genuinely not sold in comes back as a free not_available_in_country row — both free, both leave error empty, and this Actor's own testing has not yet observed Twinby returning not_available_in_country for any country checked so far (stated plainly, not papered over — see Evidence and boundaries). Default: ["ru"]. |
platforms | no | appstore, googleplay, rustore — up to 3 values, but see above: RuStore is this brand's only optional platform across the whole line, deliberately left out of the default so a fresh run isn't exposed to its antibot risk without you choosing it. Default: appstore, googleplay. |
convertToUsd | no | When true (default), every priced App Store entry gets a usd field from yesterday's ECB daily reference rate — null with an fxNote for RUB and any other currency the ECB doesn't carry. When false, no FX lookup runs at all. |
compareWithPreviousRun | no | When true, diffs each row against the last run of that exact country/platform pair under the same watchId. Default: false. |
watchId | no | Names which saved snapshot history to diff against. Pattern: [a-zA-Z0-9_-]{1,40}. Default: "default". |
maxStorefronts | no | Hard ceiling on countries × platforms for one run, enforced before any request. Range: 1 to 120. Default: 10. |
{"countries": ["ru","us"],"platforms": ["appstore","googleplay"],"convertToUsd": true}
Real happy, partial and failure output
One row per country × platform pair. Every example below is real and unedited, copied
as-is from an actual run of this exact code.
Happy path: a storefront that came back with real, priced data
App Store, Russia — the full RUB-priced plan list, this brand's own home market. Note the
Cyrillic duration names (Неделя, Месяц, 3 месяца) all collapsing to
planFamily: "Premium"durationDays, and every price's usd staying null with an
fxNote explaining exactly why:
{"recordType": "storefront_snapshot","brand": "twinby","platform": "appstore","country": "ru","appId": "1595084386","observedAt": "2026-09-26T14:42:16.151Z","status": "ok","found": true,"appTitle": "Приложение «Twinby: знакомства рядом»","rating": 4.2,"ratingCount": 55294,"ratingHistogram": {"1": 7889,"2": 1639,"3": 1963,"4": 2514,"5": 41289},"version": "2.4.0","lastUpdated": "2026-08-31T07:35:09.000Z","inAppPurchases": [{"name": "Неделя","priceText": "539,00 ₽","amount": 539,"currency": "RUB","planFamily": "Premium","durationDays": 7,"usd": null},{"name": "Месяц","priceText": "895,00 ₽","amount": 895,"currency": "RUB","planFamily": "Premium","durationDays": 30,"usd": null},{"name": "3 месяца","priceText": "1 690,00 ₽","amount": 1690,"currency": "RUB","planFamily": "Premium","durationDays": 90,"usd": null},{"name": "1 буст","priceText": "449,00 ₽","amount": 449,"currency": "RUB","planFamily": "Boost","durationDays": null,"usd": null},{"name": "5 суперлайков","priceText": "399,00 ₽","amount": 399,"currency": "RUB","planFamily": "SuperLike","durationDays": null,"usd": null},{"name": "5 бустов","priceText": "1 310,00 ₽","amount": 1310,"currency": "RUB","planFamily": "Boost","durationDays": null,"usd": null},{"name": "3 буста","priceText": "890,00 ₽","amount": 890,"currency": "RUB","planFamily": "Boost","durationDays": null,"usd": null},{"name": "Режим путешествий","priceText": "289,00 ₽","amount": 289,"currency": "RUB","planFamily": "TravelMode","durationDays": null,"usd": null},{"name": "25 суперлайков","priceText": "1 390,00 ₽","amount": 1390,"currency": "RUB","planFamily": "SuperLike","durationDays": null,"usd": null},{"name": "60 суперлайков","priceText": "1 390,00 ₽","amount": 1390,"currency": "RUB","planFamily": "SuperLike","durationDays": null,"usd": null}],"planSummary": {"Premium": {"minAmount": 539,"maxAmount": 1690,"currency": "RUB","minUsd": null,"maxUsd": null},"Boost": {"minAmount": 449,"maxAmount": 1310,"currency": "RUB","minUsd": null,"maxUsd": null},"SuperLike": {"minAmount": 399,"maxAmount": 1390,"currency": "RUB","minUsd": null,"maxUsd": null},"TravelMode": {"minAmount": 289,"maxAmount": 289,"currency": "RUB","minUsd": null,"maxUsd": null}},"fx": {"source": "ECB","date": "2026-09-25","rate": null},"fxNote": "no ECB rate for RUB","error": "","sourceUrl": "https://apps.apple.com/ru/app/id1595084386","changes": []}
Google Play, Russia — the same country, this store's genuinely different shape. No named plans (Google Play never exposes them); rating and install-count data instead:
{"recordType": "storefront_snapshot","brand": "twinby","platform": "googleplay","country": "ru","appId": "com.twinby","observedAt": "2026-09-26T14:42:16.154Z","status": "ok","found": true,"appTitle": "Twinby: Dating & Compatibility","rating": 3.8581442832946777,"ratingCount": 29900,"installs": "1M+","lastUpdated": "2026-08-27T00:00:00.000Z","containsAds": false,"iapPriceRange": null,"inAppPurchases": [],"fx": {"source": "ECB","date": "2026-09-25","rate": null},"error": "","sourceUrl": "https://play.google.com/store/apps/details?id=com.twinby&hl=en&gl=ru","changes": []}
App Store, United States — the same subscription structure, this storefront's own English names and USD prices, including both spellings of Travel Mode's own two price points.
{"recordType": "storefront_snapshot","brand": "twinby","platform": "appstore","country": "us","appId": "1595084386","observedAt": "2026-09-26T14:43:43.763Z","status": "ok","found": true,"appTitle": "Twinby: Dating & Compatibility App","rating": 4.4,"ratingCount": 2333,"ratingHistogram": {"1": 279,"2": 27,"3": 39,"4": 87,"5": 1901},"version": "2.4.0","lastUpdated": "2026-08-31T07:35:09.000Z","inAppPurchases": [{"name": "1 week","priceText": "$17.99","amount": 17.99,"currency": "USD","planFamily": "Premium","durationDays": 7,"usd": 17.99},{"name": "1 month","priceText": "$29.99","amount": 29.99,"currency": "USD","planFamily": "Premium","durationDays": 30,"usd": 29.99},{"name": "1 boost","priceText": "$8.99","amount": 8.99,"currency": "USD","planFamily": "Boost","durationDays": null,"usd": 8.99},{"name": "3 months","priceText": "$59.99","amount": 59.99,"currency": "USD","planFamily": "Premium","durationDays": 90,"usd": 59.99},{"name": "5 boosts","priceText": "$29.99","amount": 29.99,"currency": "USD","planFamily": "Boost","durationDays": null,"usd": 29.99},{"name": "5 superlikes","priceText": "$9.99","amount": 9.99,"currency": "USD","planFamily": "SuperLike","durationDays": null,"usd": 9.99},{"name": "25 superlikes","priceText": "$44.99","amount": 44.99,"currency": "USD","planFamily": "SuperLike","durationDays": null,"usd": 44.99},{"name": "Travel Mode","priceText": "$8.99","amount": 8.99,"currency": "USD","planFamily": "TravelMode","durationDays": null,"usd": 8.99},{"name": "Travel Mode","priceText": "$17.99","amount": 17.99,"currency": "USD","planFamily": "TravelMode","durationDays": null,"usd": 17.99},{"name": "3 boosts","priceText": "$24.99","amount": 24.99,"currency": "USD","planFamily": "Boost","durationDays": null,"usd": 24.99}],"planSummary": {"Premium": {"minAmount": 17.99,"maxAmount": 59.99,"currency": "USD","minUsd": 17.99,"maxUsd": 59.99},"Boost": {"minAmount": 8.99,"maxAmount": 29.99,"currency": "USD","minUsd": 8.99,"maxUsd": 29.99},"SuperLike": {"minAmount": 9.99,"maxAmount": 44.99,"currency": "USD","minUsd": 9.99,"maxUsd": 44.99},"TravelMode": {"minAmount": 8.99,"maxAmount": 17.99,"currency": "USD","minUsd": 8.99,"maxUsd": 17.99}},"fx": {"source": "ECB","date": "2026-09-25","rate": 1},"fxNote": null,"error": "","sourceUrl": "https://apps.apple.com/us/app/id1595084386","changes": []}
Partial: RuStore's real antibot challenge, honestly reported as source_error
Not a guess, not a retry loop — a real captured page shape. RuStore served this Actor's
request an antibot-challenge page instead of Twinby's real listing at capture time. This
Actor's own page-shape validation catches this — it looks for the specific appId/appName/
appType: "MAIN" structure the real listing carries, does not find it, and reports
source_error with a specific message rather than guessing at a title or rating from a page
it does not recognize:
{"recordType": "storefront_snapshot","brand": "twinby","platform": "rustore","country": null,"appId": "com.twinby","observedAt": "2026-09-26T14:42:16.463Z","status": "source_error","found": false,"error": "unexpected page shape: no appId/appName/.../appType:\"MAIN\" own-app card found","sourceUrl": "https://www.rustore.ru/catalog/app/com.twinby"}
Failure path 1: a malformed country code, rejected before any request
{"recordType": "storefront_snapshot","brand": "twinby","platform": "appstore","country": "zz","status": "invalid_country","found": false,"error": "","sourceUrl": null}
Failure path 2: the source did not answer after retries
A simulated exhausted-retries 429 for the App Store storefront, run through the real code
path — captured via the same fetchImpl injection point this line's own tests use, exactly
as described for the equivalent Tinder example (this Actor's sibling README explains the
technique in full; the row shape below is what the REAL runDatingAppIntel entry point and
REAL Apify ChargingManager produce once every retry is exhausted, with only the network
call itself scripted):
{"recordType": "storefront_snapshot","brand": "twinby","platform": "appstore","country": "us","appId": "1595084386","observedAt": "2026-09-26T16:06:47.492Z","appTitle": null,"rating": null,"ratingCount": null,"ratingHistogram": null,"installs": null,"version": null,"lastUpdated": null,"releaseNotes": null,"containsAds": null,"iapPriceRange": null,"inAppPurchases": [],"planSummary": {},"fx": null,"fxNote": null,"sourceUrl": "https://apps.apple.com/us/app/id1595084386","status": "rate_limited","found": false,"error": "http 429 after retries"}
Field dictionary
| Field | Type | Meaning |
|---|---|---|
recordType | string | Always "storefront_snapshot". |
brand | string | Always "twinby" here. |
platform | string | "appstore", "googleplay" or "rustore". |
country | string | null | The ISO-3166 code requested — null only on a rustore row, since RuStore does not vary by country the way an App Store or Google Play storefront does. |
appId | string | 1595084386 (App Store numeric id) or com.twinby (Google Play/RuStore package name), always the same two/three values regardless of country. |
observedAt | string (ISO 8601) | The exact moment this Actor read the page, in UTC. |
status | string | ok, not_available_in_country, invalid_country, rate_limited or source_error — see the examples above for a real instance of every one this brand has actually produced. |
found | boolean | true only for status: "ok". |
appTitle | string | null | The store's own title, in that storefront's own language — Приложение «Twinby: знакомства рядом» on the Russian App Store, Twinby: Dating & Compatibility App on the US one. |
rating | number | null | The store's own current average rating out of 5. |
ratingCount | number | null | Total ratings behind that average. |
ratingHistogram | object | null | App Store only — {"1":n, ..., "5":n}. Always null on googleplay/rustore. |
installs | string | null | Google Play only — the store's own bucketed label ("1M+"). Always null elsewhere. |
version | string | null | The currently listed version string. |
lastUpdated | string (ISO 8601) | null | The store's own last-update date. |
releaseNotes | string | null | "What's new" text, storefront's own language. On RuStore, this and appTitle are read from a 4000-character window after the page's own app-card anchor — a value genuinely longer than that window comes back null, indistinguishable from "field truly absent" (a known, fail-closed limitation, not a guess; see Evidence and boundaries). |
containsAds | boolean | null | Google Play only. |
iapPriceRange | object | null | Google Play only — {min, max, currency} aggregate. |
inAppPurchases | array | App Store only. Always [] on googleplay/rustore — RuStore's own public page does not expose a priced IAP list the way the App Store's does. |
inAppPurchases[].name | string | The plan's own raw name — "Неделя", "1 week", "Режим путешествий". |
inAppPurchases[].priceText / .amount / .currency | string / number|null / string|null | The storefront's own formatted price, its parsed numeric amount, and the resolved ISO-4217 code. |
inAppPurchases[].planFamily | string | See the plan dictionary table below. |
inAppPurchases[].durationDays | number | null | 7 for Неделя/1 week, 30 for Месяц/1 month, 90 for 3 месяца/3 months — parsed straight from the plan's own duration-stating name. null for Boost/SuperLike/TravelMode packs, none of which state a duration. |
inAppPurchases[].usd | number | null | amount converted via yesterday's ECB rate when convertToUsd is on and the ECB carries that currency. Always null for RUB — see What you get and Evidence and boundaries. |
planSummary | object | Per-planFamily min/max within this row. |
fx | object | null | {source: "ECB", date, rate} — rate itself is null for RUB even though the object is still populated, which is exactly why fxNote exists as a separate, explicit signal rather than relying on a caller to notice a null nested one level down. |
fxNote | string | null | "no ECB rate for RUB" on every RUB-priced row when convertToUsd is on; null otherwise. |
error | string | Empty for a clean "no" (not_available_in_country/invalid_country); a specific message for rate_limited/source_error. |
sourceUrl | string | null | The exact URL fetched; null only for invalid_country. |
changes[] | array | Populated only with compareWithPreviousRun: true. |
Plan dictionary — how planFamily is decided
| planFamily | Matched from (case-insensitive substring, longest match wins) |
|---|---|
Premium | "неделя", "месяц", "1 week", "1 month", "3 months", "premium" — every real duration-named variant this brand's own pages use for the one underlying subscription |
Boost | "буст", "boost" |
SuperLike | "суперлайк", "superlike" |
TravelMode | "режим путешествий", "travel mode" |
other | anything not matching the above |
Evidence and boundaries
What this Actor reads, exactly. Three public product pages:
https://apps.apple.com/{cc}/app/id1595084386,
https://play.google.com/store/apps/details?id=com.twinby&hl=en&gl={cc}, and, when
rustore is requested, https://www.rustore.ru/catalog/app/com.twinby.
robots.txt, checked, not assumed. apps.apple.com disallows /api/*, /v1/*,
/WebObjects/*, /includes/*, */search?*. play.google.com disallows /store/getreviews,
/store/search, /store/xhr, /store/apps/datasafety*. rustore.ru disallows */rating,
*/versions, /api/. This Actor's own fetched paths are not among any of these disallowed
paths on any of the three domains.
RuStore's page carries more than one app's data, and this Actor reads the right one.
RuStore's own catalog page embeds several apps' structured data in one document; this Actor
selects the object whose own packageName field equals com.twinby, never the first object
on the page, so a RuStore row is never accidentally another app's data mislabeled as Twinby's.
RuStore's real, live, unresolved antibot risk — stated plainly, not hidden. From this
line's own test infrastructure's network range, a RuStore request has been observed to
receive a redirect to a challenge page instead of the real listing — a genuine, reproduced
condition, not a theoretical one. This Actor does not attempt to solve or bypass that
challenge in any way; when it happens, the row comes back as a free, honestly-labeled
source_error rather than a wrong guess at the app's title or rating. This is exactly why
rustore is NOT part of this Actor's default platforms prefill: a fresh run gets Twinby's
App Store and Google Play data reliably, and only reads RuStore when you explicitly ask for
it, with the antibot risk clearly disclosed here first.
RuStore's 4000-character read window, stated plainly. appTitle and releaseNotes on a
RuStore row are read from a bounded window after the page's own app-card anchor, by design —
a value genuinely longer than that window returns null, which looks identical to "the page
truly has no value here." This is a known, fail-closed limitation (documented in this line's
own LINE_SPEC.md §7): the code refuses to guess at truncated text rather than returning a
half-decoded fragment.
RUB has no ECB rate — the single most important currency-conversion caveat for this
brand. The European Central Bank's daily reference rate feed, which this Actor uses for
every usd conversion, does not carry a Russian ruble rate. Every RUB-priced entry — which
means every price on Twinby's own Russian storefront, its largest and most-rated market —
gets usd: null and an explicit fxNote. If you need a USD figure for these prices anyway,
treat amount/currency as the ground truth and apply whatever FX source your own use case
already trusts; this Actor will not fabricate a rate from an unaudited source.
429 is a measured risk, App Store only, not a guess. From this line's own test
infrastructure's IP range, hitting Apple's App Store every 8 seconds produced 5 real 200
responses and 7 real 429s out of 12 consecutive requests. The same IP, paced at 30 seconds
between requests with a 45-second retry after any 429, produced 5 real 200s out of 5. This
Actor's own fetch layer caps concurrent requests toward Apple at 2 per run and retries a
rate-limited request with backoff before giving up and reporting rate_limited — a real
engineering response to a measured problem on a source this Actor has no control over.
Google Play has not shown an equivalent rate limit in this line's own testing, and RuStore's
own blocking behavior is the antibot challenge described above, not a simple 429.
What the App Store's own feed does NOT publish. No duration-stating text exists for
Boost/SuperLike/TravelMode packs, so durationDays is null for all of them by design, not
by omission. Age rating and an install count are likewise not published on this specific
page (install count is Google Play's own disclosure, not Apple's).
What this Actor does NOT do, and will not be extended to do. No account, no login, no profile/photo/message/match data of any real Twinby user, no review-feed reads, no store search, no private API of Twinby's, Apple's, Google's or RuStore's. Permanent design boundaries, not missing features.
Decision routing
Use this Actor when you specifically want Twinby's own subscription prices — including
the RUB/USD dual-currency story and, optionally, the RuStore read — normalized into a stable
planFamily, with rating/version data attached.
Use a general-purpose App Store, Google Play or RuStore scraper instead when you want any app's raw page data with no dating-specific normalization layer; this Actor is narrower and deliberately adds the plan-dictionary and FX-honesty layer on top.
Use one of this Actor's own siblings instead of Twinby when the brand you care about is a different dating app: the same engine also ships as separate Actors for Tinder, Bumble, Hinge and Badoo — none of which read RuStore, since Twinby is currently the only brand in this line sold there.
Do not enable platforms: ["rustore"] on an unattended production schedule without first
reading the antibot caveat above — a scheduled run that always includes RuStore will,
under the conditions described in Evidence and boundaries, sometimes get a free
source_error row instead of data. That is not a malfunction; it is this Actor honestly
reporting a real condition on RuStore's side that it does not attempt to work around.
Use convertToUsd: false when you specifically want RUB left unconverted for a downstream
FX pipeline you already run yourself — this avoids this Actor even attempting an ECB
lookup for currencies it already knows have no rate, and makes the intent explicit in your
own input rather than relying on the usd: null output to communicate it after the fact.
Do not use this Actor for anything about real Twinby users — profiles, matches, messages. No configuration will ever do that.
Commercial playbooks
Competitive benchmarking against a Russian-market-facing dating app. A product team at Tinder, Bumble or a Russian-market-specific competitor pulls Twinby's current RUB pricing directly, rather than relying on a stale screenshot, before setting or adjusting their own Russian-market subscription price.
RUB-pricing research without a borrowed exchange rate. An FX or pricing researcher uses
this Actor's raw RUB amount/currency fields, explicitly NOT the (always-null) usd
field, as a clean, unconverted primary-source input, then applies whichever FX rate their own
methodology actually trusts and can defend in a footnote.
RuStore ecosystem monitoring. An analyst tracking the RuStore alternative app-store
market runs this Actor with platforms: ["rustore"] on a schedule, accepting that some runs
will report a free source_error instead of data, and treats a string of consecutive
source_error rows over time as its own signal about RuStore's own bot-defense posture.
ASO agency monthly report for a CIS-market dating-app client. Twinby's App Store and Google Play numbers slot into the same monthly competitive-pricing report structure a growth agency already builds for its client's own ranking, rating and review-velocity trend, with Twinby specifically representing the Russian-market competitive set the client's own product usually has no other automated visibility into.
Investor and market-structure research on the CIS dating-app segment. Twinby has no public earnings disclosure of its own (private company, per SPEC.md's own ownership note), which makes its store-page numbers — rating count, install bucket, and now subscription pricing — one of the only externally-verifiable signals into how a real, actively-rated competitor in this specific regional market is priced and how its user base is growing, without relying on the company's own, unaudited marketing claims.
Integration recipes
Schedule it (Apify Console). Same mechanism as every Actor in this line — Schedules tab,
a cron expression, the input you want repeated attached. For Twinby specifically, consider
scheduling appstore/googleplay (the reliable pair) on a tight weekly cadence and
rustore separately, less frequently, given its antibot risk.
Call it from the REST API.
curl -X POST "https://api.apify.com/v2/acts/zinin~twinby-app-intel/runs?token=$APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"countries": ["ru", "us"], "platforms": ["appstore", "googleplay"], "convertToUsd": true}'
Call it from Node.js or Python via Apify's own SDK.
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('zinin/twinby-app-intel').call({countries: ['ru', 'us'],platforms: ['appstore', 'googleplay'],convertToUsd: true,});const { items } = await client.dataset(run.defaultDatasetId).listItems();
The Python client (apify-client on PyPI) mirrors the same call shape:
client.actor('zinin/twinby-app-intel').call(run_input={...}).
Wire it to a webhook. From this Actor's page or via the API's POST /v2/webhooks
endpoint, attach a webhook fired on ACTOR.RUN.SUCCEEDED pointing at your own endpoint.
Check OUTPUT.partial in the payload rather than relying on the run's overall status alone
— a run with a RuStore source_error still finishes as SUCCEEDED from the platform's own
point of view.
Call it as a tool from an LLM agent, via Apify's MCP server (https://mcp.apify.com) —
once this Actor is published, an MCP-aware agent can call it by name with the same
countries/platforms/convertToUsd input shape as any other integration path here.
Export straight to Google Sheets. Use the Dataset tab's built-in "Export data" action and
choose the Google Sheets format, or connect a Sheets-sync automation watching for
ACTOR.RUN.SUCCEEDED, to keep a live spreadsheet of Twinby's RUB and USD prices side by
side, refreshed on the same schedule as your scheduled runs.
Plain CSV/Excel for a one-off analysis. The Dataset tab's Export button produces a
CSV or Excel file of exactly the rows in that run, one row per country × platform pair,
ready to open directly in a spreadsheet — including the RUB rows with their usd: null
column, exactly as captured, with no conversion silently applied on export either.
Operating guide
Reading a partial run. Check OUTPUT.partial first. A run can succeed overall while a
RuStore storefront reports source_error or an App Store storefront reports rate_limited
— both leave the OTHER storefronts in the same run entirely unaffected.
Treat a RuStore source_error differently from an App Store rate_limited. A
rate_limited row is usually transient and worth a short-delay retry (see this line's
Tinder README for the measured numbers). A RuStore source_error caused by the antibot
challenge is NOT reliably transient in the same way — retrying immediately may hit the same
challenge again. If RuStore data matters to you, budget for occasional gaps rather than
assuming a retry will always fix it.
Choosing a watchId strategy. One watchId per logical tracking list, not per run — a
"CIS competitive pricing" watch and a "personal billing region comparison" watch should carry
different watchIds so their changes[] histories never mix. The diff is keyed per
country/platform/watchId combination, so reusing one across different lists won't
corrupt data, but it does make the resulting history harder to read later.
maxStorefronts on a large country list. If countries × platforms exceeds
maxStorefronts, the excess is dropped before any request is made and reported in one free
status: "truncated" row naming exactly what was skipped, in the same dataset as the
successful rows. Raise maxStorefronts (up to 120) for a genuinely large single run, or
split a long country list across a few scheduled runs to keep OUTPUT.deadlineHit false
(this Actor's own soft wall-clock budget is 280 seconds on the prefill-sized path).
Interpreting usd: null on a RUB row is not a bug to chase down. See Evidence and
boundaries: it is the correct, honest output for every single RUB-priced entry, every time,
by design, for as long as the ECB's own daily feed excludes the ruble. If you need a USD
figure anyway, convert amount/currency yourself with whatever FX source your own
methodology already trusts, and treat this Actor's null as a deliberate refusal to
fabricate a number it cannot vouch for — not as a gap to work around by retrying the run.
Кратко по-русски
Twinby — сервис знакомств с платной подпиской (Неделя/Месяц/3 месяца), бустами, суперлайками
и режимом путешествий. Этот Актор читает официальные страницы Twinby в App Store, Google Play
и, по желанию, в RuStore — и отдаёт точные текущие цены по каждой стране, рейтинг и версию
приложения, без входа в аккаунт и без доступа к профилям пользователей. Цены в рублях
показаны как есть, без придуманного курса: Актор не переводит рубли в доллары сам, потому что
у Европейского центробанка нет курса рубля в его ежедневной сводке — это честно указано в
каждой такой строке полем fxNote. Если ищете «цены Twinby», «сколько стоит подписка
Twinby», «Twinby App Store цена», «Twinby RuStore рейтинг» или «Twinby отзывы количество» —
здесь актуальные цифры прямо с витрин магазинов, а не оценка на глаз и не старый скриншот.
FAQ
Why is usd always null for a RUB price? Because the European Central Bank's own
daily reference rate feed — the only FX source this Actor trusts — does not publish a RUB
rate at all. This is not a bug or an oversight; every RUB-priced row will show this for as
long as the ECB's own feed excludes the ruble. See Evidence and boundaries.
Why isn't RuStore in the default input? Because RuStore has been observed serving a real, unresolved antibot challenge instead of its real listing to some networks. Leaving it out of the default keeps a first-time run reliable; add it explicitly once you've read the caveat under Evidence and boundaries and decided you want that risk.
Does a RuStore source_error mean Twinby isn't on RuStore anymore? No — it means THIS
run's request to RuStore didn't get the real page back. Twinby's own RuStore listing (SPEC.md
confirms it live) still exists; a source_error describes this Actor's read attempt, not the
app's real availability. Compare against not_available_in_country, which specifically means
the store itself said "not sold here" — the two are never the same status for exactly this
reason.
What does planFamily: "Premium" mean for a brand that doesn't call anything "Premium" on
its own page? It's this Actor's own normalized label for Twinby's one underlying
subscription, regardless of which duration or which language names it on a given storefront.
The raw, unmodified name is still there in inAppPurchases[].name if you want the brand's own
exact wording.
Can I get Twinby's rating and version from RuStore without touching the App Store or
Google Play at all? Yes — set platforms: ["rustore"] alone. You will get rating,
install count, version and release notes (subject to the antibot risk above), but never a
priced plan list, since RuStore's own public page does not expose one.
Why does the App Store list "Travel Mode" at two different prices in the same country?
Because that is genuinely what the storefront's own page lists — this Actor's own captured
US example shows $8.99 and $17.99 both under the name "Travel Mode", which this Actor
reports as two separate entries under the same planFamily: "TravelMode" rather than
picking one and discarding the other. The storefront itself does not label which is which
beyond the name and price shown; this Actor does not invent a distinguishing label that the
source itself does not provide.
Is Twinby a Match Group brand like Tinder or Hinge? No — per this line's own SPEC.md, Twinby's operator is a private company, not associated with Match Group or Bumble Inc. This Actor reads the same kind of public store data regardless of who owns the brand; it does not depend on or require any relationship with the app's own operator.
Does a not_available_in_country row exist for Twinby at all? Not yet observed in this
line's own testing across the countries checked so far — every country tried has returned
either real data or a clean invalid_country for a malformed code, never a real "this app
is not sold here" 404. That could change as Twinby's own market coverage changes; this Actor
will report it honestly the moment it happens, with the same free, zero-charge treatment
every other brand in this line already gives that status.
Will this Actor ever try to bypass RuStore's antibot challenge? No. Bypassing an
antibot/CAPTCHA mechanism is outside what this Actor is built to do or will be extended to
do — when RuStore serves a challenge instead of the real page, the honest, permanent answer
is a free source_error, not an escalating arms race with the source's own defenses.
Related app intelligence tools
- App Store App Intel — Inspect another iOS app by app ID or App Store URL.
- Google Play App Intel — Get a public Google Play app card by package ID or URL.
- App Store Customer Reviews — Collect public App Store review text for separate review analysis.
Sources and rights
Every fact in this Actor's output comes from one of three public sources: Apple's own App
Store product page at apps.apple.com/{cc}/app/id1595084386, Google's own Google Play
product page at play.google.com/store/apps/details?id=com.twinby, and, when requested,
RuStore's own public catalog page at rustore.ru/catalog/app/com.twinby. All three are pages
any visitor can open with no account; this Actor respects each domain's own published
robots.txt (Evidence and boundaries lists exactly which paths) and calls no private,
undocumented or authenticated API belonging to Twinby, Apple, Google or RuStore's own
operator (VK subsidiary, per RuStore's own public ownership disclosure).
Currency conversion, when possible, uses the European Central Bank's own published daily reference rate feed — public data, no key required, and explicitly NOT extended to a currency (RUB among them) the ECB itself does not cover.
This Actor collects no personal data of any kind and has no code path that reads, infers or stores anything about a real Twinby user. "Twinby" and its plan names are its own operator's trademarks and terminology, reported here only because they are the storefront's own public labels for its own public prices — this Actor is independent and not affiliated with, endorsed by, or operated on behalf of Twinby, Apple, Google or RuStore.
Found a wrong result, or need a case this README doesn't cover? Open an issue on this Actor's own page.