Skip to content

Instantly share code, notes, and snippets.

@nalgeon
Last active October 3, 2024 13:24
Show Gist options
  • Save nalgeon/547e95d4f6b7a8b06bcdc9de3c87856a to your computer and use it in GitHub Desktop.
Save nalgeon/547e95d4f6b7a8b06bcdc9de3c87856a to your computer and use it in GitHub Desktop.
Определить ИНН по паспортным данным человека

Определить ИНН по паспортным данным человека

В поддержку «Дадаты» часто обращаются с вопросом «как получить ИНН по паспортным данным». Налоговая служба предоставляет такой сервис, но без API.

В интернете есть несколько сайтов, которые предоставляют сервис «узнать ИНН» через API. Насколько нам известно, все они используют «неофициальный» интерфейс взаимодействия с налоговой, потому что ни официального API, ни открытых данных по ИНН не существует.

Мы в «Дадате» не хотим подключать неофициальное API налоговой: оно не отличается стабильностью работы и имеет непонятные перспективы. Если вы очень хотите получать ИНН через API — вызывайте API налоговой напрямую. Мы подготовили примеры, как это сделать на самых популярных языках — Python, PHP и JavaScript.

API налоговой бесплатное, но используете его вы на свой страх и риск. Никто не гарантирует, что оно будет работать корректно и стабильно.

Пример ответа API налоговой, если ИНН найден:

{'inn': 'xxxxxxxxxxxx', 'captchaRequired': False, 'code': 1}

Ответ API, если ИНН не найден:

{'captchaRequired': False, 'code': 0}

Примеры вызова на JS, PHP и Python — ниже.

const fetch = require("node-fetch");
function suggestInn(
surname,
name,
patronymic,
birthdate,
doctype,
docnumber,
docdate
) {
const url = "https://service.nalog.ru/inn-proc.do";
const data = {
fam: surname,
nam: name,
otch: patronymic,
bdate: birthdate,
bplace: "",
doctype: doctype,
docno: docnumber,
docdt: docdate,
c: "innMy",
captcha: "",
captchaToken: ""
};
const encoded = encode(data);
resp = fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: encoded
});
return resp;
}
function encode(data) {
encoded = Object.keys(data)
.map(
key => encodeURIComponent(key) + "=" + encodeURIComponent(data[key])
)
.join("&");
return encoded;
}
suggestInn(
"Иванов",
"Сергей",
"Владимирович",
"16.03.1982",
"21",
"45 12 229333",
"03.09.2012"
)
.then(response => {
return response.json();
})
.then(response => {
console.log(response);
});
<?php
function suggestInn($surname, $name, $patronymic, $birthdate, $doctype, $docnumber, $docdate)
{
$url = "https://service.nalog.ru/inn-proc.do";
$data = array(
"fam" => $surname,
"nam" => $name,
"otch" => $patronymic,
"bdate" => $birthdate,
"bplace" => "",
"doctype" => $doctype,
"docno" => $docnumber,
"docdt" => $docdate,
"c" => "innMy",
"captcha" => "",
"captchaToken" => ""
);
$options = array(
'http' => array(
'method' => 'POST',
'header' => array(
'Content-type: application/x-www-form-urlencoded',
),
'content' => http_build_query($data)
),
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
return $result;
}
$resp = suggestInn("Иванов", "Сергей", "Владимирович", "16.03.1982", "21", "45 12 229333", "03.09.2012");
print_r($resp);
import requests
from enum import Enum
class DocumentType(Enum):
# Паспорт гражданина СССР
passport_ussr = "01"
# Свидетельство о рождении
birth_certificate = "03"
# Паспорт иностранного гражданина
passport_foreign = "10"
# Вид на жительство в России
residence_permit = "12"
# Разрешение на временное проживание в России
residence_permit_temp = "15"
# Свидетельство о предоставлении временного убежища на территории России
asylum_certificate_temp = "19"
# Паспорт гражданина России
passport_russia = "21"
# Свидетельство о рождении, выданное уполномоченным органом иностранного государства
birth_certificate_foreign = "23"
# Вид на жительство иностранного гражданина
residence_permit_foreign = "62"
def suggest_inn(surname, name, patronymic, birthdate, doctype, docnumber, docdate):
url = "https://service.nalog.ru/inn-proc.do"
data = {
"fam": surname,
"nam": name,
"otch": patronymic,
"bdate": birthdate,
"bplace": "",
"doctype": doctype,
"docno": docnumber,
"docdt": docdate,
"c": "innMy",
"captcha": "",
"captchaToken": "",
}
resp = requests.post(url=url, data=data)
resp.raise_for_status()
return resp.json()
if __name__ == "__main__":
response = suggest_inn(
surname="Иванов",
name="Сергей",
patronymic="Владимирович",
birthdate="16.03.1982",
doctype=DocumentType.passport_russia.value,
docnumber="45 12 229333",
docdate="03.09.2012",
)
print(response)
@andreevnickolay
Copy link

Спасибо! Обращаюсь HTTP-запросом из 1С - прекрасно работает.

Добрый день! Есть возможность увидеть результат реализации?

@Avryanta
Copy link

Avryanta commented Sep 16, 2022

Спасибо! Обращаюсь HTTP-запросом из 1С - прекрасно работает.

Добрый день! Есть возможность увидеть результат реализации?

Пожалуйста: https://paste1c.ru/8gvci6l5nci
Кстати, до сих пор работает

Процедура ЗаполнитьИННПоПаспортнымДаннымНаСервере()
	
	Если НЕ ЗначениеЗаполнено(Объект.Ссылка) Тогда
		Сообщить("Перед заполнением ИНН необходимо записать элемент справочника");
		Возврат;
	КонецЕсли;
	
	Запрос = Новый Запрос("ВЫБРАТЬ
	                      |	ПодтверждающиеДокументы.Владелец.Фамилия КАК Фамилия,
	                      |	ПодтверждающиеДокументы.Владелец.Имя КАК Имя,
	                      |	ПодтверждающиеДокументы.Владелец.Отчество КАК Отчество,
	                      |	ПодтверждающиеДокументы.Владелец.ДатаРождения КАК ДатаРождения,
	                      |	ПодтверждающиеДокументы.Серия КАК Серия,
	                      |	ПодтверждающиеДокументы.Номер КАК Номер,
	                      |	ПодтверждающиеДокументы.ДатаВыдачи КАК ДатаВыдачиПаспорта
	                      |ИЗ
	                      |	Справочник.ПодтверждающиеДокументы КАК ПодтверждающиеДокументы
	                      |ГДЕ
	                      |	ПодтверждающиеДокументы.ВидПодтверждающегоДокумента = ЗНАЧЕНИЕ(Перечисление.ВидыДокументов.Паспорт)
	                      |	И ПодтверждающиеДокументы.Владелец = &Владелец
	                      |	И НЕ ПодтверждающиеДокументы.ПометкаУдаления
	                      |	И ПодтверждающиеДокументы.Текущий");
	
	Запрос.УстановитьПараметр("Владелец", Объект.Ссылка);
	
	РезультатЗапроса = Запрос.Выполнить();
	
	Если РезультатЗапроса.Пустой() Тогда
		Сообщить("У данного контрагента не занесен паспорт! Заполнение ИНН невозможно");
		Возврат;
	КонецЕсли;
	
	Выборка = РезультатЗапроса.Выбрать();
	
	Если Выборка.Следующий() Тогда
		
		СоединениеHTTP = Новый HTTPСоединение("service.nalog.ru",443,,,,10, Новый ЗащищенноеСоединениеOpenSSL(,),Ложь);
		
		Заголовки = Новый Соответствие;
		Заголовки.Вставить("Content-type", "application/x-www-form-urlencoded");
		
		СерияПаспорта = СтрЗаменить(СокрЛП(Выборка.Серия), " ", "");
		
		СерияПаспорта = Лев(СерияПаспорта, 2) + " " + Прав(СерияПаспорта, 2);
		
		АдресРесурса = "/inn-proc.do?" + 
		"fam="     + СокрЛП(Выборка.Фамилия) + 
		"&nam="    + СокрЛП(Выборка.Имя) + 
		"&otch="   + СокрЛП(Выборка.Отчество) + 
		"&bdate="  + Формат(Выборка.ДатаРождения, "ДФ=dd.MM.yyyy") + // Формат даты: 04.12.1995 
		"&bplace"  +    // Оставляем пустым
		"&doctype=21" + // Так указывается тип Паспорт на сайте 
		"&docno="  + СерияПаспорта + " " + Выборка.Номер + // Строка вида "99 99 9999990" 
		"&docdt="  + Формат(Выборка.ДатаВыдачиПаспорта, "ДФ=dd.MM.yyyy") + // Формат даты: 04.12.1995 
		"&c=innMy" + 
		"&captcha" + 
		"&captchaToken";
		
		ЗапросHTTP = Новый HTTPЗапрос(АдресРесурса, Заголовки);
		
		Попытка
			
			Ответ = СоединениеHTTP.ОтправитьДляОбработки(ЗапросHTTP);
			
		Исключение
			
			Сообщить(ОписаниеОшибки());
			
			Возврат;
			
		КонецПопытки; 
		
		Если Ответ.КодСостояния = 200 Тогда
			
			ТелоОтвета = Ответ.ПолучитьТелоКакСтроку();
			СтруктураОтвета = СтруктураИзСтрокиJSON(ТелоОтвета);
			
			Если НЕ СтруктураОтвета = Неопределено Тогда
				
				Если СтруктураОтвета.code = 1 Тогда
					
					Объект.ИНН = СтруктураОтвета.inn;
					
				ИначеЕсли СтруктураОтвета.code = 0 Тогда
					
					Сообщить("По данным ФНС не найдена информация об ИНН.
					|Рекомендуется проверить правильность введенных данных и повторить попытку поиска.");
					
				КонецЕсли;
				
			КонецЕсли;
			
		Иначе
			
			Сообщить("Сервер вернул код состояния " + Ответ.КодСостояния + Символы.ПС + ТелоОтвета = Ответ.ПолучитьТелоКакСтроку());
			
		КонецЕсли;
		
	КонецЕсли;
	
КонецПроцедуры

Функция СтруктураИзСтрокиJSON(Строка, СвойстваТипаДата = Неопределено) Экспорт
	
	ЧтениеJSON = Новый ЧтениеJSON;
	ЧтениеJSON.УстановитьСтроку(Строка);
	
	Попытка
		ЗаписьJSON = ПрочитатьJSON(ЧтениеJSON, Ложь, СвойстваТипаДата, ФорматДатыJSON.ISO);
	Исключение
		Возврат Неопределено;
	КонецПопытки;
	
	Возврат ?(ТипЗнч(ЗаписьJSON) = Тип("Структура"), ЗаписьJSON, Неопределено); 
	
КонецФункции

@andreevnickolay
Copy link

Avryanta, благодарю!

@AndrewTishkin
Copy link

Такой сервис есть у Тинькофф
https://www.tinkoff.ru/inn/
Интересно, они его всё-таки реализовали через API от ФНС или "накостылили"?

Если через API, то у Dadata есть шанс на "легальный" путь)

@kireno
Copy link

kireno commented Dec 9, 2022

Спасибо! Обращаюсь HTTP-запросом из 1С - прекрасно работает.

Добрый день! Есть возможность увидеть результат реализации?

Пожалуйста: https://paste1c.ru/8gvci6l5nci Кстати, до сих пор работает

Процедура ЗаполнитьИННПоПаспортнымДаннымНаСервере()
	
	Если НЕ ЗначениеЗаполнено(Объект.Ссылка) Тогда
		Сообщить("Перед заполнением ИНН необходимо записать элемент справочника");
		Возврат;
	КонецЕсли;
	
	Запрос = Новый Запрос("ВЫБРАТЬ
	                      |	ПодтверждающиеДокументы.Владелец.Фамилия КАК Фамилия,
	                      |	ПодтверждающиеДокументы.Владелец.Имя КАК Имя,
	                      |	ПодтверждающиеДокументы.Владелец.Отчество КАК Отчество,
	                      |	ПодтверждающиеДокументы.Владелец.ДатаРождения КАК ДатаРождения,
	                      |	ПодтверждающиеДокументы.Серия КАК Серия,
	                      |	ПодтверждающиеДокументы.Номер КАК Номер,
	                      |	ПодтверждающиеДокументы.ДатаВыдачи КАК ДатаВыдачиПаспорта
	                      |ИЗ
	                      |	Справочник.ПодтверждающиеДокументы КАК ПодтверждающиеДокументы
	                      |ГДЕ
	                      |	ПодтверждающиеДокументы.ВидПодтверждающегоДокумента = ЗНАЧЕНИЕ(Перечисление.ВидыДокументов.Паспорт)
	                      |	И ПодтверждающиеДокументы.Владелец = &Владелец
	                      |	И НЕ ПодтверждающиеДокументы.ПометкаУдаления
	                      |	И ПодтверждающиеДокументы.Текущий");
	
	Запрос.УстановитьПараметр("Владелец", Объект.Ссылка);
	
	РезультатЗапроса = Запрос.Выполнить();
	
	Если РезультатЗапроса.Пустой() Тогда
		Сообщить("У данного контрагента не занесен паспорт! Заполнение ИНН невозможно");
		Возврат;
	КонецЕсли;
	
	Выборка = РезультатЗапроса.Выбрать();
	
	Если Выборка.Следующий() Тогда
		
		СоединениеHTTP = Новый HTTPСоединение("service.nalog.ru",443,,,,10, Новый ЗащищенноеСоединениеOpenSSL(,),Ложь);
		
		Заголовки = Новый Соответствие;
		Заголовки.Вставить("Content-type", "application/x-www-form-urlencoded");
		
		СерияПаспорта = СтрЗаменить(СокрЛП(Выборка.Серия), " ", "");
		
		СерияПаспорта = Лев(СерияПаспорта, 2) + " " + Прав(СерияПаспорта, 2);
		
		АдресРесурса = "/inn-proc.do?" + 
		"fam="     + СокрЛП(Выборка.Фамилия) + 
		"&nam="    + СокрЛП(Выборка.Имя) + 
		"&otch="   + СокрЛП(Выборка.Отчество) + 
		"&bdate="  + Формат(Выборка.ДатаРождения, "ДФ=dd.MM.yyyy") + // Формат даты: 04.12.1995 
		"&bplace"  +    // Оставляем пустым
		"&doctype=21" + // Так указывается тип Паспорт на сайте 
		"&docno="  + СерияПаспорта + " " + Выборка.Номер + // Строка вида "99 99 9999990" 
		"&docdt="  + Формат(Выборка.ДатаВыдачиПаспорта, "ДФ=dd.MM.yyyy") + // Формат даты: 04.12.1995 
		"&c=innMy" + 
		"&captcha" + 
		"&captchaToken";
		
		ЗапросHTTP = Новый HTTPЗапрос(АдресРесурса, Заголовки);
		
		Попытка
			
			Ответ = СоединениеHTTP.ОтправитьДляОбработки(ЗапросHTTP);
			
		Исключение
			
			Сообщить(ОписаниеОшибки());
			
			Возврат;
			
		КонецПопытки; 
		
		Если Ответ.КодСостояния = 200 Тогда
			
			ТелоОтвета = Ответ.ПолучитьТелоКакСтроку();
			СтруктураОтвета = СтруктураИзСтрокиJSON(ТелоОтвета);
			
			Если НЕ СтруктураОтвета = Неопределено Тогда
				
				Если СтруктураОтвета.code = 1 Тогда
					
					Объект.ИНН = СтруктураОтвета.inn;
					
				ИначеЕсли СтруктураОтвета.code = 0 Тогда
					
					Сообщить("По данным ФНС не найдена информация об ИНН.
					|Рекомендуется проверить правильность введенных данных и повторить попытку поиска.");
					
				КонецЕсли;
				
			КонецЕсли;
			
		Иначе
			
			Сообщить("Сервер вернул код состояния " + Ответ.КодСостояния + Символы.ПС + ТелоОтвета = Ответ.ПолучитьТелоКакСтроку());
			
		КонецЕсли;
		
	КонецЕсли;
	
КонецПроцедуры

Функция СтруктураИзСтрокиJSON(Строка, СвойстваТипаДата = Неопределено) Экспорт
	
	ЧтениеJSON = Новый ЧтениеJSON;
	ЧтениеJSON.УстановитьСтроку(Строка);
	
	Попытка
		ЗаписьJSON = ПрочитатьJSON(ЧтениеJSON, Ложь, СвойстваТипаДата, ФорматДатыJSON.ISO);
	Исключение
		Возврат Неопределено;
	КонецПопытки;
	
	Возврат ?(ТипЗнч(ЗаписьJSON) = Тип("Структура"), ЗаписьJSON, Неопределено); 
	
КонецФункции

Добрый день, а сейчас работает у вас?

@SergeyPominov
Copy link

SergeyPominov commented Dec 10, 2022

У меня скрипт последнее время перестал работать, но сегодня он выдал:
{"code":100,"captchaRequired":false}
Сталкивался кто то с такой проблемой, и если да то как ее решить?

@Avryanta
Copy link

@kireno @SergeyPominov Хмм, если перейти на https://service.nalog.ru/inn.do, то страница больше не доступна в принципе

@Trider12
Copy link

405 Not Allowed

@Ichinya
Copy link

Ichinya commented Feb 19, 2024

Такой сервис есть у Тинькофф https://www.tinkoff.ru/inn/ Интересно, они его всё-таки реализовали через API от ФНС или "накостылили"?

Спасибо за подсказку. Сделал у себя дополнительно через Тинькофф.

@aav1984
Copy link

aav1984 commented Feb 20, 2024

@Avryanta Спасибо за наводку и пример. Если что - до сих пор работает.
зы.: только лучше бы вы в тело упаковали перс.данные, от греха.

`Для каждого эл из СтруктураПараметров Цикл

	СтрокаЗапроса = эл.Ключ+"="+эл.Значение+"&"+СтрокаЗапроса; 

КонецЦикла;

СтрокаЗапроса = КодироватьСтроку(СтрокаЗапроса,СпособКодированияСтроки.URLВКодировкеURL);

HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаЗапроса);`

Где в структуре ключ-значение параметров запроса (аналогично топик стартеру).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment