ptgc
MTProto client for Dart

Getting Started

ptgc requires Dart SDK ^3.5.0, and a Telegram account you’re willing to automate — this is a real user login, not a bot.

1. Install the package

dart pub add ptgc

Or add it to pubspec.yaml directly, then run dart pub get:

dependencies:
  ptgc: ^1.0.0

2. Get an API ID and hash

  1. Sign in to my.telegram.org/apps with the phone number you’ll be automating.
  2. Fill in the “Create new application” form — the name and description can be anything.
  3. Copy the api_id (a number) and api_hash (a hex string) it gives you.
  4. Keep them somewhere safe and never commit them to version control. Anyone with your api_hash can impersonate your app.

3. Load your credentials

Create a .env file next to pubspec.yaml:

API_ID=1234567
API_HASH=0123456789abcdef0123456789abcdef

Add .env to .gitignore. ptgc reads this with penv under the hood — see Configuration for alternatives (a different file name, passing credentials directly, and so on).

4. Log in

import 'package:ptgc/ptgc.dart';

Future<void> main() async {
  final client = TelegramClient.fromEnv();
  await client.connect();

  if (!client.isSignedIn) {
    final sent = await client.auth.sendCode('+15551234567');
    print('Enter the code Telegram sent you:');
    final code = stdin.readLineSync()!.trim();

    final result = await client.auth.signIn(code: code, phoneCodeHash: sent.phoneCodeHash);
    if (result.status == SignInStatus.passwordRequired) {
      print('Enter your 2FA password (hint: ${result.passwordHint}):');
      await client.auth.checkPassword(stdin.readLineSync()!.trim());
    }
  }

  final me = await client.whoAmI();
  print('Logged in as ${me.displayName}');

  await client.disconnect();
}

The first run walks you through the code (and password, if you have Two-Factor Authentication enabled) once. TelegramClient.connect() saves the resulting session to ptgc.session.json by default, so every run after that skips straight past isSignedIn. See Authentication Flow for the full picture, including what each SignInStatus means.

5. Do something with it

final chats = await client.chats.listDialogs(limit: 20);
for (final chat in chats) {
  print('${chat.title} (${chat.kind})');
}

6. Run it

dart run bin/my_script.dart

Next steps

  • Wrap login and API calls in try/catch — see Error Handling.
  • Browse the Examples to add member management, invite links, or raw MTProto calls.
  • Look up any method’s exact signature in the API Reference.