NetSendo
Guides & Tips

SMS z polskimi znakami: dlaczego tylko 70 znaków?

NetSendo Team13 min czytania
SMS z polskimi znakami: dlaczego tylko 70 znaków?

SMS mieści 160 znaków tylko wtedy, gdy każdy znak należy do alfabetu GSM-7. Wystarczy jedna polska litera (ą, ć, ę, ł, ń, ó, ś, ź, ż), emotka albo „drukarski” cudzysłów, a cała wiadomość przechodzi na kodowanie UCS-2, w którym jeden SMS ma 70 znaków, a dłuższe wiadomości dzielą się co 67 znaków zamiast co 153. Operatorzy i bramki liczą opłatę za każdą część, więc jeden znak potrafi podwoić koszt wysyłki.

W skrócie: Jedna część SMS-a to 140 bajtów. GSM-7 mieści w nich 160 znaków po 7 bitów, UCS-2 potrzebuje 16 bitów na znak i mieści 70. W wiadomościach wieloczęściowych nagłówek zabiera miejsce, więc zostaje 153 (GSM-7) albo 67 (UCS-2) znaków na część, a płacisz za każdą. Żadna polska litera diakrytyczna nie należy do GSM-7, a znaki € [ ] { } \ ~ ^ | liczą się podwójnie. Przed dużą wysyłką sprawdź liczbę części u swojego dostawcy.

Dlaczego SMS ma 160 znaków, a z polskimi znakami tylko 70?

Bo jedna część SMS-a ma stały ładunek 140 bajtów (1120 bitów), a kodowanie decyduje, ile znaków się w nim zmieści. GSM-7 zapisuje znak na 7 bitach, więc 1120 ÷ 7 = 160 znaków; UCS-2 używa 16 bitów na znak, więc 1120 ÷ 16 = 70 znaków.

Dokumentacja AWS End User Messaging SMS mówi to wprost: wiadomość złożona wyłącznie ze znaków zestawu GSM 03.38 może mieć do 160 znaków, a wiadomość z dowolnym znakiem spoza niego – do 70. To przełączenie działa na zasadzie „wszystko albo nic”. Kodowanie wybiera się dla całej wiadomości, nie dla pojedynczych znaków, więc 159 zwykłych liter i jedno „ł” wysyłasz w całości w UCS-2.

GSM-7 (GSM 03.38)

Domyślny, 7-bitowy alfabet SMS ze standardu GSM. Obejmuje litery łacińskie A–Z i a–z, cyfry, typowe znaki interpunkcyjne, kilka liter zachodnioeuropejskich (np. é, ä, ö, ü, ñ, à) i część wielkich liter greckich. Nie ma w nim żadnej polskiej litery diakrytycznej.

UCS-2

Stałe, 16-bitowe kodowanie Unicode, którego telefon i bramka używają, gdy wiadomość zawiera choć jeden znak spoza GSM-7. Obsłuży niemal każde pismo, ale w jednej części zmieści mniej niż połowę znaków.

Dlaczego długie SMS-y dzielą się co 153 i co 67 znaków?

Gdy wiadomość nie mieści się w jednej części, każda część dostaje nagłówek UDH (User Data Header), dzięki któremu telefon składa je w całość – a nagłówek zabiera miejsce na tekst. W GSM-7 kosztuje 7 znaków, więc zostaje 153 na część; w UCS-2 kosztuje 3 znaki, więc zostaje 67.

Twilio podaje te same liczby: 160 znaków dla pojedynczej części GSM-7, 153 na część w wiadomości wieloczęściowej, 70 dla pojedynczej części UCS-2 i 67 na każdą kolejną.

W praktyce SMS o długości 161 znaków to nie „jeden SMS i jeden znak”. To dwie części po maksymalnie 153 znaki, a pojemność dwóch części to 306 znaków, nie 320. Tabela pokazuje, od której długości zaczyna się kolejna część.

Liczba części (płatnych SMS-ów)Maks. długość GSM-7 (znaki)Maks. długość UCS-2 (znaki)
116070
2306134
3459201
4612268
5765335
101530670

Wyliczone dla 160/153 i 70/67 znaków na część. Stan na listopad 2026.

Dostawcy ograniczają też całkowitą długość. SMSAPI przyjmuje do 1530 znaków (670 ze znakami specjalnymi) w maksymalnie 10 częściach i zaznacza, że polskie litery to znaki specjalne. AWS przyjmuje 1530 znaków GSM albo 630 znaków spoza GSM, a Twilio podaje 1600 i 700 i zaleca, by SMS nie przekraczał 320 znaków. Sprawdź limit swojego dostawcy, zanim zbudujesz długie szablony.

Które znaki przełączają SMS na Unicode (UCS-2)?

Każdy znak, którego nie ma w tabeli GSM 03.38. W polskich wiadomościach winowajcy to prawie zawsze trzy grupy: litery z ogonkami i kreskami, znaki typograficzne wstawiane przez edytory tekstu oraz emotki.

Pełną tabelę GSM 03.38 publikuje AWS. Zestawienie z alfabetami kilku języków pokazuje, dlaczego ta sama kampania kosztuje jedną część po niemiecku i dwie po polsku:

JęzykLitery, które zostają w GSM-7Litery, które wymuszają UCS-2
polskiżadna z polskich liter diakrytycznych✗ ą ć ę ł ń ó ś ź ż i ich wielkie odpowiedniki
niemiecki✓ ä ö ü ß Ä Ö Üżadna ze standardowych liter
hiszpański~ ñ Ñ é É ü Ü ¿ ¡✗ á í ó ú Á Í Ó Ú
angielski✓ wszystkie literycudzysłowy drukarskie, półpauza, pauza, wielokropek

Na podstawie tabeli znaków GSM 03.38 opublikowanej przez AWS. Stan na listopad 2026.

Najwięcej niespodzianek robią znaki, których nikt świadomie nie wpisał:

  • Cudzysłowy i apostrofy drukarskie („ ” ’): Word, Dokumenty Google i macOS zamieniają proste cudzysłowy automatycznie. AWS pokazuje 130-znakową wiadomość, która wymaga dwóch części tylko przez jeden apostrof ’ w „Dr. Salazar’s”.
  • Półpauza, pauza i wielokropek (– — …): zwykły dywiz (-) jest w GSM-7, półpauza i wielokropek jako jeden znak – nie.
  • Niewidoczne znaki: twarda spacja albo spacja o zerowej szerokości skopiowana ze strony lub z CMS-a wygląda jak zwykła spacja, ale wymusza UCS-2.
  • Emotki: żadnej nie ma w GSM-7. Według Twilio emotka zajmuje 2 z 70 znaków części UCS-2, a emotki z modyfikatorami (np. kolorem skóry) jeszcze więcej.
⚠️ Uwaga: Personalizacja zmienia kodowanie osobno dla każdego odbiorcy. „Cześć [[fname]]” to oczywiście UCS-2, ale nawet „Czesc [[fname]]” zostaje w GSM-7 dla Anny i przechodzi na UCS-2 dla Łukasza czy Józefa. Ten sam szablon może więc kosztować jedną część u jednego kontaktu i dwie u drugiego.

Które znaki GSM-7 liczą się jako dwa?

Dziewięć znaków drukowalnych leży w tabeli rozszerzeń GSM-7 i każdy wysyłany jest jako znak ucieczki plus sam znak, więc zajmuje dwa z 160 (lub 153) miejsc: ^ { } \ [ ] ~ | €.

Nie przełączają wiadomości na UCS-2, ale skracają limit. „Cena: 20€ [promocja]” to 20 znaków na ekranie i 23 w GSM-7. W zwykłym tekście różnica jest niewielka, w wiadomościach z kodami, JSON-em czy linkami z nawiasami – spora. Gdy wiadomość jest blisko granicy, pisz „EUR” zamiast „€” albo zamień nawiasy kwadratowe na okrągłe.

Jeśli licznik i tabela kiedyś się nie zgadzają, wierz liczbie części, którą dostawca zwraca po wysyłce – za nią płacisz.

Ile kosztują polskie znaki w SMS-ie?

Każda część to osobno płatny SMS. Twilio pisze, że rozlicza SMS-y za każdą wysłaną część, AWS – za liczbę części, a SMSAPI wysyła długie wiadomości jako maksymalnie 10 połączonych SMS-ów rozliczanych według cennika. Wiadomość, która urosła z jednej do dwóch części, podwaja koszt wysyłki.

Tabela mnoży oficjalne ceny za część przez 1000 odbiorców. To ceny katalogowe SMS-ów wychodzących z publicznych stron dostawców, bez rabatów ilościowych, opłat operatorskich i VAT.

Dostawca i krajCena za część1000 × 1 część1000 × 2 części1000 × 3 części
SMSAPI → Polska (prepaid, najniższy próg)0,17 zł netto170 zł340 zł510 zł
Twilio → Polska0,0457 USD45,70 USD91,40 USD137,10 USD
Twilio → Niemcy0,112 USD112,00 USD224,00 USD336,00 USD
Twilio → Hiszpania0,0875 USD87,50 USD175,00 USD262,50 USD

Ceny Twilio według stron Twilio („current as of October 2026”), cennik SMSAPI sprawdzony w listopadzie 2026. Stan na listopad 2026.

Przykład pokazuje, jak niewiele trzeba. Oba teksty mówią to samo; pierwszy ma 94 znaki z polskimi literami i idzie jako dwie części UCS-2, drugi to te same 94 znaki bez ogonków i mieści się w jednej części GSM-7:

Cześć Anna, Twoje zamówienie 1042 zostało wysłane. Śledź: https://ex.co/t/1042 STOP=rezygnacja
→ UCS-2, 94 znaki, 2 części

Czesc Anna, Twoje zamowienie 1042 zostalo wyslane. Sledz: https://ex.co/t/1042 STOP=rezygnacja
→ GSM-7, 94 znaki, 1 część

Przy 10 000 odbiorców w SMSAPI to różnica między 1700 a 3400 zł netto za jedną wysyłkę – przy tych samych słowach.

Czy wysyłać SMS-y bez polskich znaków?

To zależy od rodzaju wiadomości i od odbiorcy. Usunięcie ogonków (transliteracja) utrzymuje wiadomość w GSM-7 i może obniżyć koszt o połowę, ale pogarsza czytelność i bywa odbierane jako niedbałość – to kompromis, nie reguła.

✅ Zalety

  • Do 160 znaków w jednej części zamiast 70; do 153 na część zamiast 67.
  • Przewidywalny koszt: imiona z polskimi literami nie wypychają pojedynczych odbiorców do kolejnej części.
  • SMS-y transakcyjne bez polskich znaków są w Polsce powszechne, więc odbiorcy są do nich przyzwyczajeni.

❌ Na co uważać

  • Niektóre słowa zmieniają znaczenie: „sąd” staje się „sadem”, „łączka” wygląda dziwnie jako „laczka”.
  • Marka, która wszędzie dba o język, w SMS-ie bez ogonków może wyglądać niechlujnie.
  • Imiona i nazwy miejscowości są zapisane błędnie, co w wiadomościach osobistych razi najbardziej.

Nie musisz usuwać ogonków ręcznie. SMSAPI ma parametr normalize, który zamienia znaki specjalne na odpowiedniki (ą→a, ć→c, ę→e), a według dokumentacji domyślnym kodowaniem jest windows-1250, chyba że przekażesz inne, np. utf-8. Twilio oferuje Smart Encoding, które zamienia część znaków spoza GSM na odpowiedniki i prostuje cudzysłowy.

Rozsądny kompromis: zostaw polskie znaki w krótkich wiadomościach, które i tak mieszczą się w 70 znakach, a transliteruj tylko wtedy, gdy tekst inaczej wymagałby kolejnej części. Cokolwiek wybierzesz, ustal to raz i stosuj konsekwentnie.

Czy link, tekst rezygnacji i nazwa nadawcy się liczą?

Link i tekst rezygnacji liczą się do długości, bo są częścią treści; alfanumeryczna nazwa nadawcy nie, bo jedzie w polu adresu SMS-a, a nie w tekście.

Linki

Pełny adres z parametrami UTM łatwo zajmuje 80–120 znaków, czyli ponad połowę części GSM-7. Używaj krótkiej ścieżki we własnej domenie (np. https://ex.co/t/1042) zamiast długiego linku śledzącego. Krótki link we własnej domenie pokazuje też Twoją markę i nie zależy od zewnętrznego skracacza.

Tekst rezygnacji

Marketingowe SMS-y zwykle zawierają instrukcję rezygnacji; szczegółowe wymogi zależą od kraju. „STOP=rezygnacja” to 15 znaków – uwzględnij je w każdym szablonie od początku, zamiast dopisywać na końcu i odkrywać drugą część. Pisz go bez polskich liter, żeby sam nie przełączał wiadomości na UCS-2. Zasady zgód opisuje poradnik o automatyzacji e-mail i SMS na własnym serwerze. To nie jest porada prawna.

Wstawki personalizacyjne

Imię, numer zamówienia czy kod rabatowy zmieniają końcową długość. Testuj szablony z najdłuższymi realnymi wartościami, a nie z „Ania”, i pamiętaj, że wartość z polską literą zmienia kodowanie dla tego odbiorcy.

Jak sprawdzić liczbę części przed wysyłką?

Przepuść ostateczny tekst, z wypełnionymi wstawkami, przez licznik znający tabelę GSM 03.38, a potem potwierdź wynik u dostawcy na wysyłce testowej. Liczy się liczba części podana przez dostawcę – za nią płacisz.

  1. Znajdź znaki spoza GSM

    Użyj licznika, który pokazuje konkretne znaki wymuszające UCS-2, a nie tylko sumę. Funkcja w Pythonie poniżej robi to offline.

  2. Testuj z najdłuższymi wartościami

    Wypełnij wstawki najdłuższymi imionami i kodami z bazy oraz imionami z polskimi literami.

  3. Wyślij testowy SMS na swój telefon

    Sprawdź, jak wygląda, czy części przychodzą połączone i czy link działa.

  4. Odczytaj liczbę części u dostawcy

    Twilio zwraca num_segments w zasobie wiadomości, SMSAPI – parts i koszt w punktach. Porównaj z szacunkiem przed wysyłką do całej listy.

Funkcja korzysta z tabeli GSM 03.38 z dokumentacji AWS, liczy znaki rozszerzeń podwójnie, a emotki jako dwie jednostki UCS-2. To szacunek: bramki mogą nie dzielić znaku ucieczki ani emotki między dwie części, co przy samej granicy czasem dokłada część.

import math

GSM7_BASIC = set(
    "@£$¥èéùìòÇ\nØø\rÅåΔ_ΦΓΛΩΠΨΣΘΞÆæßÉ !\"#¤%&'()*+,-./0123456789:;<=>?"
    "¡ABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÑܧ¿abcdefghijklmnopqrstuvwxyzäöñüà"
)
GSM7_EXTENDED = set("\f^{}\\[]~|€")  # each costs 2 septets (ESC + char)


def sms_segments(text: str) -> dict:
    non_gsm = sorted({c for c in text if c not in GSM7_BASIC | GSM7_EXTENDED})
    if not non_gsm:
        units = sum(2 if c in GSM7_EXTENDED else 1 for c in text)
        single, per_part, encoding = 160, 153, "GSM-7"
    else:
        units = len(text.encode("utf-16-le")) // 2  # emoji = 2 units
        single, per_part, encoding = 70, 67, "UCS-2"
    parts = 1 if units <= single else math.ceil(units / per_part)
    return {"encoding": encoding, "units": units, "parts": parts,
            "non_gsm": non_gsm}


if __name__ == "__main__":
    import sys
    print(sms_segments(sys.stdin.read().rstrip("\n")))

Zapisz ją jako sms_segments.py i przekaż wiadomość na wejście:

echo "Zażółć gęślą jaźń" | python3 sms_segments.py
# {'encoding': 'UCS-2', 'units': 17, 'parts': 1, 'non_gsm': ['ó', 'ą', 'ć', 'ę', 'ł', 'ń', 'ś', 'ź', 'ż']}

Lista non_gsm pokazuje dokładnie, który znak zamienić.

📋 Checklist

  • Brak cudzysłowów drukarskich, półpauz, wielokropków i twardych spacji z edytora
  • Decyzja: polskie znaki zostają czy transliteracja
  • Znaki rozszerzeń (€ [ ] { } \ ~ ^ |) policzone podwójnie
  • Tekst rezygnacji i krótki link wliczone w długość
  • Szablon przetestowany z najdłuższymi wartościami wstawek
  • Liczba części potwierdzona u dostawcy na wysyłce testowej

Liczba części SMS-ów wysyłanych z NetSendo

NetSendo wysyła SMS-y przez Twilio, Vonage, MessageBird, Plivo albo SMSAPI, a opisane zasady dzielenia na części to zasady dostawcy, nie NetSendo. W praktyce liczą się dwie rzeczy.

Po pierwsze, licznik w edytorze SMS to szybki szacunek. Oznacza wiadomość jako Unicode, gdy tylko pojawi się dowolny znak spoza ASCII, i dzieli długość przez 160 albo 70. Niemiecki tekst z „ü” zobaczysz więc jako Unicode, choć GSM-7 ma „ü”, a wiadomości tuż nad granicą części mogą zostać policzone o jedną część za mało, bo licznik nie stosuje reguły 153/67. Traktuj go jak kontrolkę ostrzegawczą, a teksty graniczne sprawdzaj funkcją powyżej.

Po drugie, prawdziwą liczbę dostajesz po wysyłce. Webhook sms.sent zawiera pola parts i credits dla każdej wiadomości, wzięte z odpowiedzi dostawcy (w SMSAPI parts i punkty, w Twilio num_segments). Możesz je zbierać w n8n przez node NetSendo albo dowolnym endpointem opisanym w dokumentacji webhooków, zweryfikować podpis HMAC-SHA256 i dostać alert, gdy kampania ma średnio więcej części, niż planowałeś. NetSendo wysyła do SMSAPI z encoding=utf-8, więc polskie znaki dochodzą tak, jak je napisałeś; jeśli chcesz je usunąć, zrób to w treści. SMS-y wyślesz też przez REST API.

ℹ️ Uwaga: Wysyłka SMS w starszych wersjach NetSendo nie działała; wersja 2.2.0 naprawiła zadanie wysyłki SMS, a 2.7.2 kampanie wysyłane z panelu i testowy SMS. Zanim oprzesz się na SMS-ach, zaktualizuj NetSendo do bieżącej wersji.

🎯 Rady eksperta

1
Pisz SMS-y w zwykłym edytorze tekstu

Szablony twórz w edytorze kodu albo bezpośrednio w edytorze SMS, nigdy w Wordzie czy Dokumentach Google, które same wstawiają „drukarskie” cudzysłowy i półpauzy.

2
Planuj 140 znaków, nie 160 (albo 60, nie 70)

Zostaw miejsce na tekst rezygnacji i dłuższe wartości wstawek, żeby długie imię nie dokładało części.

3
Zdecyduj o ogonkach świadomie

Z polskimi literami piszesz na 70 znaków; bez nich – na 160. Obie drogi są w porządku, byle konsekwentne.

4
Po każdej kampanii sprawdzaj liczbę części

Porównaj średnią liczbę części na wiadomość z planem. Skok zwykle oznacza, że do szablonu wkradł się znak spoza GSM.

Najczęściej zadawane pytania

Dlaczego SMS z polskimi znakami ma tylko 70 znaków?

Żadna polska litera diakrytyczna nie należy do alfabetu GSM-7, więc jedna litera ą, ł czy ś przełącza całą wiadomość na kodowanie UCS-2. UCS-2 zapisuje znak na 16 bitach, więc w 140 bajtach jednej części mieści się 70 znaków.

Ile znaków ma SMS z polskimi znakami składający się z kilku części?

67 znaków na część, bo każda część zawiera nagłówek łączący. Dwie części mieszczą więc 134 znaki, trzy – 201.

Czy emotka w SMS-ie liczy się jako jeden znak?

Nie. Emotka przełącza wiadomość na UCS-2 i według Twilio zajmuje 2 z 70 znaków części; emotki z modyfikatorami zajmują więcej.

Czy lepiej wysyłać SMS-y bez polskich znaków?

Bez polskich znaków wiadomość zostaje w GSM-7 i mieści do 160 znaków, co może obniżyć koszt o połowę. Kosztem jest gorsza czytelność i wygląd, więc to decyzja zależna od rodzaju wiadomości i marki.

Które znaki liczą się w SMS-ie podwójnie?

Znaki z tabeli rozszerzeń GSM-7: ^ { } \ [ ] ~ | oraz €. Każdy zajmuje dwa miejsca, ale nie przełącza wiadomości na UCS-2.

Czy SMSAPI może samo usunąć polskie znaki?

Tak, parametr normalize=1 zamienia znaki specjalne na odpowiedniki, np. ą na a i ć na c. Domyślnym kodowaniem SMSAPI jest windows-1250, chyba że przekażesz inne.

Źródła

Wysyłaj e-maile i SMS-y z własnego serwera

NetSendo działa na Twojej infrastrukturze i łączy się z dostawcą SMS, którego już używasz.

#sms#sms-marketing#encoding#unicode#twilio
Udostępnij