{"id":498937,"date":"2026-10-16T13:58:43","date_gmt":"2026-10-16T10:58:43","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=498937"},"modified":"2026-10-16T13:58:43","modified_gmt":"2026-10-16T10:58:43","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=498937","title":{"rendered":"Where to Buy Telegram Stars: Prices and a Python Guide to Fragment"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>I wanted to buy Telegram Stars for less, so I compared the same packages on three websites. SMMESE had the lowest listed price of the three: $15.31 for 1,000 Stars, compared with $16.50 on TgSuperstars and $16.67 on MyStars.tg.<\/p>\n<p>I then traced how a service finds the recipient, pays from its own wallet, and confirms the order. The Python implementation below can become the part of your own Stars website that fulfills purchases.<\/p>\n<h2>Where to buy Telegram Stars and what they cost<\/h2>\n<p>Listed prices in USD, checked on <strong>October 16, 2026<\/strong>:<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th>\n<p align=\"left\">Website<\/p>\n<\/th>\n<th>\n<p align=\"left\">100 Stars<\/p>\n<\/th>\n<th>\n<p align=\"left\">500 Stars<\/p>\n<\/th>\n<th>\n<p align=\"left\">1,000 Stars<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><a href=\"https:\/\/smmese.com\/en\/telegram-stars\" rel=\"noopener nofollow\">SMMESE<\/a><\/p>\n<\/td>\n<td>\n<p align=\"left\">$1.54<\/p>\n<\/td>\n<td>\n<p align=\"left\">$7.66<\/p>\n<\/td>\n<td>\n<p align=\"left\">$15.31<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><a href=\"https:\/\/tgsuperstars.com\/en\/\" rel=\"noopener nofollow\">TgSuperstars<\/a><\/p>\n<\/td>\n<td>\n<p align=\"left\">$1.65<\/p>\n<\/td>\n<td>\n<p align=\"left\">$8.25<\/p>\n<\/td>\n<td>\n<p align=\"left\">$16.50<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\"><a href=\"https:\/\/mystars.tg\/\" rel=\"noopener nofollow\">MyStars.tg<\/a><\/p>\n<\/td>\n<td>\n<p align=\"left\">$1.68<\/p>\n<\/td>\n<td>\n<p align=\"left\">$8.34<\/p>\n<\/td>\n<td>\n<p align=\"left\">$16.67<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>For SMMESE, I selected Cryptocurrency; the calculator marked the total as fee included. TgSuperstars accepts USDT or GRAM through its TON-wallet payment option, and other cryptocurrencies through Heleket. MyStars.tg lists GRAM and USDT payments. Both ask for the recipient\u2019s Telegram username and the number of Stars.<\/p>\n<p>These are the prices displayed before payment. Network or exchange withdrawal fees can add to the amount spent. MyStars.tg also states that paying through Cryptomus adds a separate processor fee, so compare the final checkout total as well as the listed price.<\/p>\n<h2>What a Stars seller does after payment<\/h2>\n<p>On sites such as <a href=\"https:\/\/smmese.com\/en\/telegram-stars\" rel=\"noopener nofollow\">SMMESE<\/a>, the buyer can specify their own or another recipient\u2019s Telegram username. The implementation I examined buys Stars through Fragment using the service\u2019s wallet. The recipient gets the Stars; the service pays for the purchase. That separates the customer\u2019s payment from the transaction used to fulfill the order.<\/p>\n<p>A storefront built this way needs to cover the Fragment purchase, currency conversion, payment-processing costs, and its margin. Its order handler also needs to distinguish an accepted payment from a completed purchase: a timeout can leave the outcome unknown even after a transaction has reached the network.<\/p>\n<h2>Automating Telegram Stars purchases with Python<\/h2>\n<p><code>fragment.py<\/code> calls Fragment\u2019s internal web methods from an authenticated browser session. <code>worker.py<\/code> checks the quote, calls the wallet signer, and tracks the order. These excerpts use the project\u2019s shared models, settings, store, and wallet module.<\/p>\n<h3>1. Connect the browser session and verify the wallet<\/h3>\n<p>Playwright connects to an already running Chromium instance. The code extracts the <code>\/api?hash=\u2026<\/code> endpoint from the Fragment page and makes requests inside the browser with its cookies.<\/p>\n<p>It checks that the authorized wallet matches the service\u2019s signing wallet. If necessary, <code>checkTonProofAuth<\/code> proves ownership before the purchase request is created.<\/p>\n<h3>2. Find the recipient<\/h3>\n<p>Stars purchases use three methods:<\/p>\n<pre><code class=\"python\">\"stars\": (    \"searchStarsRecipient\",    \"initBuyStarsRequest\",    \"getBuyStarsLink\",)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper\"><\/span><\/a><\/div><\/pre>\n<p><code>searchStarsRecipient<\/code> takes the Telegram username and returns an internal <code>recipient<\/code> value, plus the display name and avatar when available. Show that profile to the buyer so they can check the destination. The next request needs the returned <code>recipient<\/code>, not an arbitrary Telegram user ID.<\/p>\n<h3>3. Create the purchase request<\/h3>\n<p>Inside <code>Fragment.quote()<\/code>, <code>_lookup()<\/code> finds the recipient and <code>initBuyStarsRequest<\/code> creates the request:<\/p>\n<pre><code class=\"python\">page = await self._page(gift.product)await self._own_session(page)session = await self._session(page)_lookup_method, init_method, link_method = METHODS[gift.product]token = (await self._lookup(page, gift))[\"recipient\"]init_params = {    \"recipient\": token,    \"payment_method\": (        \"usdt_ton\" if gift.currency == \"USDT\" else \"ton\"    ),}field = \"quantity\" if gift.product == \"stars\" else \"months\"init_params[field] = str(getattr(gift, field))initial = await self._rpc(page, init_method, init_params)identifier = request_id(initial)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p><code>gift<\/code> holds the purchase parameters. Stars use <code>quantity<\/code>; the same module supports Premium through <code>months<\/code>. <code>payment_method<\/code> selects <code>ton<\/code> or <code>usdt_ton<\/code>. The response supplies the request ID; no payment has been sent yet.<\/p>\n<h3>4. Get and validate the payment quote<\/h3>\n<p><code>getBuyStarsLink<\/code> receives the request ID, wallet information, and the sender-visibility setting:<\/p>\n<pre><code class=\"python\">link = await self._rpc(    page,    link_method,    {        \"id\": identifier,        \"transaction\": \"1\",        \"show_sender\": \"1\" if gift.show_sender else \"0\",        \"account\": json.dumps(            self.signer.account(), separators=(\",\", \":\")        ),        \"device\": json.dumps(DEVICE, separators=(\",\", \":\")),    },)if link.get(\"ok\") is False:    raise ServiceError(        \"fragment_invalid_quote\",        \"Fragment did not return a payment quote\",    )if await self._session(page) != session:    raise ServiceError(        \"fragment_session_changed\",        \"The Fragment account changed during quoting\",    )quote = validate_transaction(    link,    self.signer.address,    self.settings,    currency=gift.currency,)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>The response contains the destination, amount, expiry, and payment payload. The session check catches an account change during quoting; <code>validate_transaction()<\/code> checks the proposed transaction against the configured wallet and rules.<\/p>\n<p>For TON payments, validation checks the allowed destination and message structure. USDT transfers have separate token checks. The method also saves Fragment\u2019s <code>confirm_method<\/code> and <code>confirm_params<\/code> for confirmation after payment.<\/p>\n<h3>5. Check the spending limit, sign, and save before sending<\/h3>\n<p>The purchase price may change between checkout and fulfillment. The worker rejects a price above the order\u2019s limit:<\/p>\n<pre><code class=\"python\">price = (    quote[\"token_amount_units\"]    if request.currency == \"USDT\"    else quote[\"amount_nanotons\"])if price &gt; request.max_units:    raise ServiceError(        \"price_limit_exceeded\",        \"Fragment price exceeds the order limit\",        409,    )<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>It checks the TON balance, including a fee reserve, and leaves enough time before the quote expires. USDT orders also require a separate token-balance check.<\/p>\n<pre><code class=\"python\">state = await self.chain.state(self.signer.address)required_ton = (    quote[\"amount_nanotons\"]    + self.settings.fee_reserve_nanotons)if state.balance &lt; required_ton:    raise ServiceError(        \"insufficient_balance\",        \"Insufficient TON balance including the network fee reserve\",        409,    )if (    quote[\"valid_until\"]    &lt; int(time.time()) + self.settings.min_validity_seconds):    raise ServiceError(        \"quote_expired\",        \"The payment quote expired before signing\",        409,    )<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>The signer prepares the transaction using the wallet\u2019s current state:<\/p>\n<pre><code class=\"python\">signed = await self.signer.sign(    quote,    state.seqno,    state.state,)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>Before broadcasting, the worker records the signed BOC\u2014the serialized message\u2014along with the quote and order state:<\/p>\n<pre><code class=\"python\">order = self.store.transition(    identifier,    (\"preparing\",),    \"signed\",    quote=quote,    **asdict(signed),    before_lt=state.last_transaction_lt,    currency=request.currency,    **prices,    fee_reserve_ton=ton_string(        self.settings.fee_reserve_nanotons    ),    broadcast_attempts=0,)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p><code>prices<\/code> contains the cost fields prepared earlier. Only after the store write succeeds does the worker broadcast:<\/p>\n<pre><code class=\"python\">await self.broadcast(order)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p>Saving first lets the worker continue with the same signed payment after an interruption.<\/p>\n<h3>6. Confirm the existing payment and complete the order<\/h3>\n<p>If broadcasting times out, <code>reconcile()<\/code> checks the existing payment through the blockchain module. Under the permitted retry conditions, the worker rebroadcasts the saved BOC instead of signing a new purchase.<\/p>\n<p>Once the blockchain check reports success, the order becomes <code>paid<\/code>. The worker then calls <code>Fragment.confirm()<\/code> with the saved quote and signed BOC:<\/p>\n<pre><code class=\"python\">result = await self.fragment.confirm(    order[\"detail\"][\"quote\"],    order[\"detail\"][\"boc\"],)if result.get(\"confirmed\"):    self.store.transition(        order[\"id\"],        (\"paid\",),        \"completed\",        delivery_id=result[\"delivery_id\"],        error_code=None,        message=\"Fragment confirmed the purchase\",    )<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><span class=\"sc-logo-wrapper icon-only\"><\/span><\/a><\/div><\/pre>\n<p><code>Fragment.confirm()<\/code> checks for <code>ok: true<\/code> in Fragment\u2019s response. A successful confirmation moves the order to <code>completed<\/code>; confirmation errors leave it <code>paid<\/code> and awaiting completion. A paid order must not start another purchase just because confirmation is delayed.<\/p>\n<h2>Connecting the purchase handler to your own website<\/h2>\n<p>The storefront needs a recipient-and-quantity form, customer payment processing, and an order queue. After the server verifies the customer\u2019s payment with the payment provider, it can queue the purchase for this handler.<\/p>\n<p>Keep the customer payment reference, recipient, Fragment request, signed BOC, and status associated with the same order. This gives the worker enough information to resume checks after a failure. A redirect to a successful-payment page alone is not proof that the customer paid.<\/p>\n<\/div>\n<p>\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/1095242\/\">https:\/\/habr.com\/ru\/articles\/1095242\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>I wanted to buy Telegram Stars for less, so I compared the same packages on three websites. SMMESE had the lowest listed price of the three: $15.31 for 1,000 Stars, compared with $16.50 on TgSuperstars and $16.67 on MyStars.tg.I then traced how a service finds the recipient, pays from its own wallet, and confirms the order. The Python implementation below can become the part of your own Stars website that fulfills purchases.Where to buy Telegram Stars and what they costListed prices in USD, checked on October 16, 2026:Website100 Stars500 Stars1,000 StarsSMMESE$1.54$7.66$15.31TgSuperstars$1.65$8.25$16.50MyStars.tg$1.68$8.34$16.67For SMMESE, I selected Cryptocurrency; the calculator marked the total as fee included. TgSuperstars accepts USDT or GRAM through its TON-wallet payment option, and other cryptocurrencies through Heleket. MyStars.tg lists GRAM and USDT payments. Both ask for the recipient\u2019s Telegram username and the number of Stars.These are the prices displayed before payment. Network or exchange withdrawal fees can add to the amount spent. MyStars.tg also states that paying through Cryptomus adds a separate processor fee, so compare the final checkout total as well as the listed price.What a Stars seller does after paymentOn sites such as SMMESE, the buyer can specify their own or another recipient\u2019s Telegram username. The implementation I examined buys Stars through Fragment using the service\u2019s wallet. The recipient gets the Stars; the service pays for the purchase. That separates the customer\u2019s payment from the transaction used to fulfill the order.A storefront built this way needs to cover the Fragment purchase, currency conversion, payment-processing costs, and its margin. Its order handler also needs to distinguish an accepted payment from a completed purchase: a timeout can leave the outcome unknown even after a transaction has reached the network.Automating Telegram Stars purchases with Pythonfragment.py calls Fragment\u2019s internal web methods from an authenticated browser session. worker.py checks the quote, calls the wallet signer, and tracks the order. These excerpts use the project\u2019s shared models, settings, store, and wallet module.1. Connect the browser session and verify the walletPlaywright connects to an already running Chromium instance. The code extracts the \/api?hash=\u2026 endpoint from the Fragment page and makes requests inside the browser with its cookies.It checks that the authorized wallet matches the service\u2019s signing wallet. If necessary, checkTonProofAuth proves ownership before the purchase request is created.2. Find the recipientStars purchases use three methods:&#187;stars&#187;: (    &#171;searchStarsRecipient&#187;,    &#171;initBuyStarsRequest&#187;,    &#171;getBuyStarsLink&#187;,)searchStarsRecipient takes the Telegram username and returns an internal recipient value, plus the display name and avatar when available. Show that profile to the buyer so they can check the destination. The next request needs the returned recipient, not an arbitrary Telegram user ID.3. Create the purchase requestInside Fragment.quote(), _lookup() finds the recipient and initBuyStarsRequest creates the request:page = await self._page(gift.product)await self._own_session(page)session = await self._session(page)_lookup_method, init_method, link_method = METHODS[gift.product]token = (await self._lookup(page, gift))[&#171;recipient&#187;]init_params = {    &#171;recipient&#187;: token,    &#171;payment_method&#187;: (        &#171;usdt_ton&#187; if gift.currency == &#171;USDT&#187; else &#171;ton&#187;    ),}field = &#171;quantity&#187; if gift.product == &#171;stars&#187; else &#171;months&#187;init_params[field] = str(getattr(gift, field))initial = await self._rpc(page, init_method, init_params)identifier = request_id(initial)gift holds the purchase parameters. Stars use quantity; the same module supports Premium through months. payment_method selects ton or usdt_ton. The response supplies the request ID; no payment has been sent yet.4. Get and validate the payment quotegetBuyStarsLink receives the request ID, wallet information, and the sender-visibility setting:link = await self._rpc(    page,    link_method,    {        &#171;id&#187;: identifier,        &#171;transaction&#187;: &#171;1&#187;,        &#171;show_sender&#187;: &#171;1&#187; if gift.show_sender else &#171;0&#187;,        &#171;account&#187;: json.dumps(            self.signer.account(), separators=(&#171;,&#187;, &#171;:&#187;)        ),        &#171;device&#187;: json.dumps(DEVICE, separators=(&#171;,&#187;, &#171;:&#187;)),    },)if link.get(&#171;ok&#187;) is False:    raise ServiceError(        &#171;fragment_invalid_quote&#187;,        &#171;Fragment did not return a payment quote&#187;,    )if await self._session(page) != session:    raise ServiceError(        &#171;fragment_session_changed&#187;,        &#171;The Fragment account changed during quoting&#187;,    )quote = validate_transaction(    link,    self.signer.address,    self.settings,    currency=gift.currency,)The response contains the destination, amount, expiry, and payment payload. The session check catches an account change during quoting; validate_transaction() checks the proposed transaction against the configured wallet and rules.For TON payments, validation checks the allowed destination and message structure. USDT transfers have separate token checks. The method also saves Fragment\u2019s confirm_method and confirm_params for confirmation after payment.5. Check the spending limit, sign, and save before sendingThe purchase price may change between checkout and fulfillment. The worker rejects a price above the order\u2019s limit:price = (    quote[&#171;token_amount_units&#187;]    if request.currency == &#171;USDT&#187;    else quote[&#171;amount_nanotons&#187;])if price &gt; request.max_units:    raise ServiceError(        &#171;price_limit_exceeded&#187;,        &#171;Fragment price exceeds the order limit&#187;,        409,    )It checks the TON balance, including a fee reserve, and leaves enough time before the quote expires. USDT orders also require a separate token-balance check.state = await self.chain.state(self.signer.address)required_ton = (    quote[&#171;amount_nanotons&#187;]    + self.settings.fee_reserve_nanotons)if state.balance &lt; required_ton:    raise ServiceError(        &#171;insufficient_balance&#187;,        &#171;Insufficient TON balance including the network fee reserve&#187;,        409,    )if (    quote[&#171;valid_until&#187;]    &lt; int(time.time()) + self.settings.min_validity_seconds):    raise ServiceError(        &#171;quote_expired&#187;,        &#171;The payment quote expired before signing&#187;,        409,    )The signer prepares the transaction using the wallet\u2019s current state:signed = await self.signer.sign(    quote,    state.seqno,    state.state,)Before broadcasting, the worker records the signed BOC\u2014the serialized message\u2014along with the quote and order state:order = self.store.transition(    identifier,    (&#171;preparing&#187;,),    &#171;signed&#187;,    quote=quote,    **asdict(signed),    before_lt=state.last_transaction_lt,    currency=request.currency,    **prices,    fee_reserve_ton=ton_string(        self.settings.fee_reserve_nanotons    ),    broadcast_attempts=0,)prices contains the cost fields prepared earlier. Only after the store write succeeds does the worker broadcast:await self.broadcast(order)Saving first lets the worker continue with the same signed payment after an interruption.6. Confirm the existing payment and complete the orderIf broadcasting times out, reconcile() checks the existing payment through the blockchain module. Under the permitted retry conditions, the worker rebroadcasts the saved BOC instead of signing a new purchase.Once the blockchain check reports success, the order becomes paid. The worker then calls Fragment.confirm() with the saved quote and signed BOC:result = await self.fragment.confirm(    order[&#171;detail&#187;][&#171;quote&#187;],    order[&#171;detail&#187;][&#171;boc&#187;],)if result.get(&#171;confirmed&#187;):    self.store.transition(        order[&#171;id&#187;],        (&#171;paid&#187;,),        &#171;completed&#187;,        delivery_id=result[&#171;delivery_id&#187;],        error_code=None,        message=&#187;Fragment confirmed the purchase&#187;,    )Fragment.confirm() checks for ok: true in Fragment\u2019s response. A successful confirmation moves the order to completed; confirmation errors leave it paid and awaiting completion. A paid order must not start another purchase just because confirmation is delayed.Connecting the purchase handler to your own websiteThe storefront needs a recipient-and-quantity form, customer payment processing, and an order queue. After the server verifies the customer\u2019s payment with the payment provider, it can queue the purchase for this handler.Keep the customer payment reference, recipient, Fragment request, signed BOC, and status associated with the same order. This gives the worker enough information to resume checks after a failure. A redirect to a successful-payment page alone is not proof that the customer paid.\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 https:\/\/habr.com\/ru\/articles\/1095242\/<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-498937","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/498937","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=498937"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/498937\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=498937"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=498937"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=498937"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}