<metaproperty="description"content="Telegram Passport is a unified authorization method for services that require personal identification. Users can upload…">
<metaproperty="og:description"content="Telegram Passport is a unified authorization method for services that require personal identification. Users can upload…">
<p><strong>Telegram Passport</strong> is a unified authorization method for services that require personal identification. Users can upload their documents once, then instantly share their data with services that require real-world ID (finance, ICOs, etc.). Telegram doesn't have access to the users' personal information thanks to end-to-end encryption.</p>
<p>From the perspective of a service that requires real-world ID, the process looks like this:</p>
<ul>
<li>A user presses "Log in with Telegram" on your <strong>website</strong> or in your <strong>app</strong>.</li>
<li>You <ahref="#requesting-information">request</a> the <ahref="#fields">data</a> you need.</li>
<li>The user accepts your <ahref="#privacy-policy">privacy policy</a> and agrees to share their data.</li>
<li>The user's Telegram app downloads and decrypts the data you requested from the end-to-end encrypted storage on Telegram.</li>
<li>If some of the data you requested is missing, the user can add it to their Telegram Passport at this point.</li>
<li>The user's app encrypts the data with your <ahref="#generating-your-public-key">public key</a> and sends it to you.</li>
<li>You <ahref="#decrypting-data">decrypt</a> the data, check it for <ahref="#fixing-errors">errors</a> and re-request any missing or invalid information.</li>
<li>You sign the user up for your service. <strong>Tada!</strong></li>
</ul>
<p>Check out <ahref="https://core.telegram.org/passport/example">this example</a> to see Telegram Passport in action.</p>
<blockquote>
<p>To learn more about Telegram Passport from the perspective of a user, please see <ahref="https://telegram.org/blog/passport">this blog post</a> and the <ahref="/api/passport">technical MTProto documentation</a>.
See <ahref="/passport/encryption">this page</a> if you're interested in encryption algorithms used on Telegram's side.</p>
<li>Added support for requesting <strong>several documents of one type</strong>. See the new objects <ahref="#passportscope">PassportScope</a>, <ahref="#passportscopeelement">PassportScopeElement</a>, <ahref="#passportscopeelementone">PassportScopeElementOneOfSeveral</a> and <ahref="#passportscopeelementone">PassportScopeElementOne</a>.</li>
<li>Added support for <strong>middle names</strong>.</li>
<li>Added support for requesting certified <strong>English translations</strong> for documents (see <ahref="#fields">Fields</a>; new field <em>translation</em> also added to the <ahref="#securevalue">SecureValue</a> object). <strong>Note:</strong> Please only request translations <em>after</em> you have received a valid document that requires one.</li>
<li>Added support for requesting <strong>names</strong> in the language of the user's country of residence (if other than English). New fields <em>first_name_native</em>, <em>last_name_native</em> and <em>middle_name_native</em> added to the <ahref="#personaldetails">PersonalDetails</a> object.</li>
<li>Replaced the <em>payload</em> parameter with the new parameter <em>nonce</em>, which serves the same function, to make the purpose more obvious (see <ahref="#request-parameters">Request Parameters</a> and the <ahref="#credentials">Credentials</a> object).</li>
<li>Updated the <ahref="/passport/example">example page</a> to support the new functionality.</li>
</ul>
<h3><aclass="anchor"href="#setting-up-telegram-passport"id="setting-up-telegram-passport"name="setting-up-telegram-passport"><iclass="anchor-icon"></i></a>Setting Up Telegram Passport</h3>
<p>To integrate Telegram Passport into your login or verification flow, you need a working Telegram bot (see <ahref="/bots#3-how-do-i-create-a-bot">this page</a> for information on how to get one).</p>
<p>To request data from Telegram Passport users, your bot will need to generate a pair of encryption keys.</p>
<h4><aclass="anchor"href="#generating-a-private-key"id="generating-a-private-key"name="generating-a-private-key"><iclass="anchor-icon"></i></a>Generating a private key</h4>
<p>First, use a console to generate a <strong>private</strong> key:</p>
<p><strong>WARNING: Keep your private key SECRET!</strong></p>
<h4><aclass="anchor"href="#generating-your-public-key"id="generating-your-public-key"name="generating-your-public-key"><iclass="anchor-icon"></i></a>Generating your public key</h4>
<p>Then use the console to print the corresponding <strong>public</strong> key:</p>
<p>Add a link to your Privacy Policy by using the <strong>/setprivacypolicy</strong> command. Users will see this link when offered to authorize you to access their data.</p>
<p>This object represents a requested element, should be one of:</p>
<ul>
<li><ahref="#passportscopeelementoneofseveral">PassportScopeElementOneOfSeveral</a> - use to request any one of the documents included in the scope.</li>
<li><ahref="#passportscopeelementone">PassportScopeElementOne</a>–use to request one particular document.</li>
<p>This object represents several elements one of which must be provided.</p>
<tableclass="table">
<tbody>
<tr>
<td><strong>Field</strong></td>
<td><strong>Type</strong></td>
<td><strong>Description</strong></td>
</tr>
<tr>
<td>one_of</td>
<td>Array of <ahref="#passportscopeelementone">PassportScopeElementOne</a></td>
<td>List of elements one of which must be provided; must contain either several of “passport”, “driver_license”, “identity_card”, “internal_passport” <strong>or</strong> several of “utility_bill”, “bank_statement”, “rental_agreement”, “passport_registration”, “temporary_registration”</td>
</tr>
<tr>
<td>selfie</td>
<td>Boolean</td>
<td><em>Optional.</em> Use this parameter if you want to request a selfie with the document from this list that the user chooses to upload.</td>
</tr>
<tr>
<td>translation</td>
<td>Boolean</td>
<td><em>Optional.</em> Use this parameter if you want to request a translation of the document from this list that the user chooses to upload. <strong>Note:</strong> We suggest to only request translations <em>after</em> you have received a valid document that requires one.</td>
<p>This object represents one particular element that must be provided. If no options are needed, <em>String</em> can be used instead of this object to specify the type of the element.</p>
<tableclass="table">
<tbody>
<tr>
<td><strong>Field</strong></td>
<td><strong>Type</strong></td>
<td><strong>Description</strong></td>
</tr>
<tr>
<td>type</td>
<td>String</td>
<td>Element type. One of "personal_details", "passport", "driver_license", "identity_card", "internal_passport", "address", "utility_bill", "bank_statement", "rental_agreement", "passport_registration", "temporary_registration", "phone_number", "email"</td>
</tr>
<tr>
<td>selfie</td>
<td>Boolean</td>
<td><em>Optional.</em> Use this parameter if you want to request a selfie with the document as well. Available for "passport", "driver_license", "identity_card" and "internal_passport"</td>
</tr>
<tr>
<td>translation</td>
<td>Boolean</td>
<td><em>Optional.</em> Use this parameter if you want to request a translation of the document as well. Available for "passport", "driver_license", "identity_card", "internal_passport", "utility_bill", "bank_statement", "rental_agreement", "passport_registration" and "temporary_registration". <strong>Note:</strong> We suggest to only request translations <em>after</em> you have received a valid document that requires one.</td>
</tr>
<tr>
<td>native_names</td>
<td>Boolean</td>
<td><em>Optional.</em> Use this parameter to request the first, last and middle name of the user in the language of the user's country of residence. Available for "personal_details"</td>
</tr>
</tbody>
</table>
<p>You can also use the special type "id_document" as an alias for one of "passport", "driver_license", "identity_card" and the special type "address_document" as an alias for one of "utility_bill", "bank_statement", "rental_agreement".
So <code>{"type":"id_document",selfie:true}</code> is equal to <code>{"one_of":["passport","driver_license","identity_card"],selfie:true}</code>.</p>
<p>Your bot can request personal details, one or several types of identity document, residential address, one or several types of proof of address document, a phone number, or an email address. You can also request optional <strong>selfies</strong> with the document and certified <strong>English translations</strong> of the document.
This is just a list of data types that can be requested, and the encrypted objects that will contain such data.</p>
<blockquote>
<p><strong>Note:</strong> We suggest to only request English translations <em>after</em> you have received a valid document that requires one.</p>
<tr><tdrowspan="2">utility_bill</td><td>files</td><td>Array of <ahref="#passportfile">PassportFile</a></td><tdrowspan="2">Utility Bill</td></tr>
<tr><td>translation</td><td><i>Optional.</i> Array of <ahref="#passportfile">PassportFile</a></td></tr>
<tr><tdrowspan="2">bank_statement</td><td>files</td><td>Array of <ahref="#passportfile">PassportFile</a></td><tdrowspan="2">Bank Statement</td></tr>
<tr><td>translation</td><td><i>Optional.</i> Array of <ahref="#passportfile">PassportFile</a></td></tr>
<tr><tdrowspan="2">rental_agreement</td><td>files</td><td>Array of <ahref="#passportfile">PassportFile</a></td><tdrowspan="2">Rental Agreement</td></tr>
<tr><td>translation</td><td><i>Optional.</i> Array of <ahref="#passportfile">PassportFile</a></td></tr>
<tr><tdrowspan="2">passport_registration</td><td>files</td><td>Array of <ahref="#passportfile">PassportFile</a></td><tdrowspan="2">Registration Page in the Internal Passport</td></tr>
<tr><td>translation</td><td><i>Optional.</i> Array of <ahref="#passportfile">PassportFile</a></td></tr>
<tr><tdrowspan="2">temporary_registration</td><td>files</td><td>Array of <ahref="#passportfile">PassportFile</a></td><tdrowspan="2">Temporary Registration</td></tr>
<tr><td>translation</td><td><i>Optional.</i> Array of <ahref="#passportfile">PassportFile</a></td></tr>
<p>This object represents a <ahref="/bots/api#passportfile">PassportFile</a> related to a document. The file is up to 10 MB in size and in the .jpg format.</p>
<p>When the user confirms your request by pressing the 'Authorize' button, the Bot API sends an <ahref="/bots/api#update">Update</a> with the field <em>passport_data</em> to the bot that contains encrypted <ahref="/bots/api#passportdata">Telegram Passport data</a>.</p>
<blockquote>
<p>Note that all base64-encoded fields should be decoded before use.</p>
<p>To decrypt the received data, first, decrypt the credentials contained in <ahref="/bots/api#encryptedcredentials">EncryptedCredentials</a>.</p>
<ol>
<li>
<p>Decrypt the credentials secret ( <em>secret</em> field in <ahref="/bots/api#encryptedcredentials">EncryptedCredentials</a>) using your <strong>private</strong> key (set OAEP padding option, e.g. <code>OPENSSL_PKCS1_OAEP_PADDING</code> in PHP)</p>
</li>
<li>
<p>Use this secret and the credentials hash ( <em>hash</em> field in <ahref="/bots/api#encryptedcredentials">EncryptedCredentials</a>) to calculate <em>credentials_key</em> and <em>credentials_iv</em> as described below:</p>
<p>Decrypt the credentials data ( <em>data</em> field in <ahref="/bots/api#encryptedcredentials">EncryptedCredentials</a>) by AES256-CBC using these <em>credentials_key</em> and <em>credentials_iv</em>. <strong>IMPORTANT:</strong> At this step, make sure that the credentials hash is equal to <code>SHA256( credentials_data )</code></p>
</li>
<li>
<p>Credentials data is padded with 32 to 255 random padding bytes to make its length divisible by 16 bytes. The first byte contains the length of this padding (including this byte). Remove the padding to get the data.</p>
</li>
</ol>
<blockquote>
<p>Note that all hashes represent as raw binary data, not hexits</p>
<p>This object represents the credentials required to decrypt encrypted data. All fields are optional and depend on <ahref="#fields">fields</a> that were requested.</p>
<tableclass="table">
<tbody>
<tr>
<td><strong>Field</strong></td>
<td><strong>Type</strong></td>
<td><strong>Description</strong></td>
</tr>
<tr>
<td>personal_details</td>
<td><ahref="#securevalue">SecureValue</a></td>
<td><em>Optional.</em> Credentials for encrypted personal details</td>
</tr>
<tr>
<td>passport</td>
<td><ahref="#securevalue">SecureValue</a></td>
<td><em>Optional.</em> Credentials for encrypted passport</td>
</tr>
<tr>
<td>internal_passport</td>
<td><ahref="#securevalue">SecureValue</a></td>
<td><em>Optional.</em> Credentials for encrypted internal passport</td>
</tr>
<tr>
<td>driver_license</td>
<td><ahref="#securevalue">SecureValue</a></td>
<td><em>Optional.</em> Credentials for encrypted driver license</td>
</tr>
<tr>
<td>identity_card</td>
<td><ahref="#securevalue">SecureValue</a></td>
<td><em>Optional.</em> Credentials for encrypted ID card</td>
</tr>
<tr>
<td>address</td>
<td><ahref="#securevalue">SecureValue</a></td>
<td><em>Optional.</em> Credentials for encrypted residential address</td>
</tr>
<tr>
<td>utility_bill</td>
<td><ahref="#securevalue">SecureValue</a></td>
<td><em>Optional.</em> Credentials for encrypted utility bill</td>
</tr>
<tr>
<td>bank_statement</td>
<td><ahref="#securevalue">SecureValue</a></td>
<td><em>Optional.</em> Credentials for encrypted bank statement</td>
</tr>
<tr>
<td>rental_agreement</td>
<td><ahref="#securevalue">SecureValue</a></td>
<td><em>Optional.</em> Credentials for encrypted rental agreement</td>
</tr>
<tr>
<td>passport_registration</td>
<td><ahref="#securevalue">SecureValue</a></td>
<td><em>Optional.</em> Credentials for encrypted registration from internal passport</td>
</tr>
<tr>
<td>temporary_registration</td>
<td><ahref="#securevalue">SecureValue</a></td>
<td><em>Optional.</em> Credentials for encrypted temporary registration</td>
<p>This object represents the credentials required to decrypt encrypted values. All fields are optional and depend on the type of <ahref="#fields">fields</a> that were requested.</p>
<td><em>Optional.</em> Credentials for encrypted Telegram Passport data. Available for "personal_details", "passport", "driver_license", "identity_card", "internal_passport" and "address" types.</td>
<td><em>Optional.</em> Credentials for an encrypted document's front side. Available for "passport", "driver_license", "identity_card" and "internal_passport".</td>
<td><em>Optional.</em> Credentials for an encrypted selfie of the user with a document. Available for "passport", "driver_license", "identity_card" and "internal_passport".</td>
</tr>
<tr>
<td>translation</td>
<td>Array of <ahref="#filecredentials">FileCredentials</a></td>
<td><em>Optional.</em> Credentials for an encrypted translation of the document. Available for "passport", "driver_license", "identity_card", "internal_passport", "utility_bill", "bank_statement", "rental_agreement", "passport_registration" and "temporary_registration".</td>
</tr>
<tr>
<td>files</td>
<td>Array of <ahref="#filecredentials">FileCredentials</a></td>
<td><em>Optional.</em> Credentials for encrypted files. Available for "utility_bill", "bank_statement", "rental_agreement", "passport_registration" and "temporary_registration" types.</td>
<p>These credentials can be used to decrypt encrypted data from the <em>data</em> field in <ahref="/bots/api#encryptedpassportelement">EncryptedPassportElement</a>.</p>
<tableclass="table">
<tbody>
<tr>
<td><strong>Field</strong></td>
<td><strong>Type</strong></td>
<td><strong>Description</strong></td>
</tr>
<tr>
<td>data_hash</td>
<td>String</td>
<td>Checksum of encrypted data</td>
</tr>
<tr>
<td>secret</td>
<td>String</td>
<td>Secret of encrypted data</td>
</tr>
</tbody>
</table>
<ol>
<li>
<p>To decrypt data, use the corresponding secret and data_hash from <ahref="#datacredentials">DataCredentials</a> as described below:</p>
<p>Use AES256-CBC with this <em>data_key</em> and <em>data_iv</em> to decrypt the data (the <em>data</em> field in <ahref="/bots/api#encryptedpassportelement">EncryptedPassportElement</a>). <strong>IMPORTANT:</strong> At this step, make sure that data_hash from the credentials is equal to <code>SHA256( data )</code>.</p>
</li>
<li>
<p>The data is padded with 32 to 255 random padding bytes to make its length divisible by 16 bytes. The first byte contains the length of the padding (including this byte). Remove padding to get the data.</p>
</li>
<li>
<p>The data is a JSON-serialized object of one of the following types: <ahref="#personaldetails">PersonalDetails</a>, <ahref="#iddocumentdata">IdDocumentData</a>, <ahref="#residentialaddress">ResidentialAddress</a>, depending on <ahref="#fields">type</a>.</p>
<p>These credentials can be used to decrypt encrypted files from the <em>front_side</em>, <em>reverse_side</em>, <em>selfie</em>, <em>files</em> and <em>translation</em> fields in <ahref="/bots/api#encryptedpassportelement">EncryptedPassportElement</a>.</p>
<tableclass="table">
<tbody>
<tr>
<td><strong>Field</strong></td>
<td><strong>Type</strong></td>
<td><strong>Description</strong></td>
</tr>
<tr>
<td>file_hash</td>
<td>String</td>
<td>Checksum of encrypted file</td>
</tr>
<tr>
<td>secret</td>
<td>String</td>
<td>Secret of encrypted file</td>
</tr>
</tbody>
</table>
<ol>
<li>
<p>To decrypt the file, use the corresponding secret and file_hash from <ahref="#filecredentials">FileCredentials</a> as described below:</p>
<p>Download the encrypted file using the <ahref="/bots/api#getfile">getFile</a> method.</p>
</li>
<li>
<p>Use AES256-CBC with this <em>file_key</em> and <em>file_iv</em> to decrypt the content of the file. <strong>IMPORTANT:</strong> At this step, make sure that file_hash from the credentials is equal to <code>SHA256( file_content )</code>.</p>
</li>
<li>
<p>The content of the file is padded with 32 to 255 random padding bytes to make its length divisible by 16 bytes. The first byte contains the length of the padding (including that byte). Remove padding to get the file content.</p>
<p>If the data you received contains errors, the bot can use the <ahref="/bots/api#setpassportdataerrors">setPassportDataErrors</a> method to inform the userand <ahref="#requesting-information">request information</a> again. The user will not be able to resend the data, until all errors are fixed.</p></div>
</div>
</div>
</div>
<divclass="footer_wrap">
<divclass="footer_columns_wrap footer_desktop">
<divclass="footer_column footer_column_telegram">
<h5>Telegram</h5>
<divclass="footer_telegram_description"></div>
Telegram is a cloud-based mobile and desktop messaging app with a focus on security and speed.