Datablist의 Company to LinkedIn API를 사용하면 Python에서 웹사이트를 기반으로 LinkedIn 회사 페이지를 찾을 수 있습니다. 도메인만 입력하거나 전체 웹사이트 URL을 전송한 뒤 매칭 작업이 끝날 때까지 기다리면 회사명, 웹사이트, LinkedIn 회사 URL, 신뢰도 신호를 받을 수 있습니다.

이 가이드에서는 Python과 Requests 라이브러리를 사용해 5개 회사 웹사이트를 매칭합니다. 익숙한 소프트웨어 기업뿐 아니라 아웃도어 장비 회사 VAUDE와 가상 데이터룸 기업 Drooms도 예시에 포함했습니다. 그런 다음 결과를 회사 리서치를 바로 시작할 수 있는 항목과 수동 확인이 필요한 항목, 두 개의 로컬 큐로 분류합니다.

🔑 바쁜 분을 위한 핵심 요약

Account 목록에 있는 웹사이트를 Datablist의 Company to LinkedIn API로 전송하세요. API가 LinkedIn 회사 페이지 URL과 신뢰도 신호를 반환하므로, 바로 활용할 관계와 검토가 필요한 관계를 구분할 수 있습니다.

  • Input: 도메인 및 회사 웹사이트 전체 URL
  • Output: 회사명, 매칭된 웹사이트, LinkedIn 회사 페이지 URL, high 또는 low 신뢰도. 결과는 Ready for research와 Needs review 큐로 분류됩니다.

💡 No-code 방식을 선호하시나요? 코드를 작성하지 않고 회사 웹사이트와 LinkedIn 페이지를 매칭하려면 Datablist의 LinkedIn Company Pages & Domain Lookup을 사용하세요.

Python과 Datablist API Key 설정하기

이 예시에서는 requests 패키지를 사용합니다. API는 HTTP로 작동하므로, 나중에 같은 요청 흐름을 다른 언어에도 적용할 수 있습니다.

REST API를 이용할 수 있는 Datablist 계정이 필요하며, 이 기능은 Growth 플랜에서 제공됩니다. 매칭에 성공하면 enrichment credit도 차감됩니다. 정확한 credit 계산 방법은 뒤에서 설명합니다.

작업 디렉터리와 find_linkedin_company_pages.py 파일을 만든 다음, 가상 환경을 생성하고 Requests를 설치하세요.

shell
mkdir company-linkedin-matcher
cd company-linkedin-matcher
python -m venv .venv
source .venv/bin/activate
python -m pip install requests
touch find_linkedin_company_pages.py

Datablist 계정에서 Personal API Key를 생성한 뒤 환경 변수로 내보냅니다.

shell
export DATABLIST_API_KEY="your-api-key"

스크립트는 이 값을 읽어 X-API-Key 헤더에 담아 전송합니다.

Python 함수 하나로 LinkedIn 회사 페이지 찾기

예시에서는 다음 5개 source account를 사용합니다.

  • account-datablist: datablist.com
  • account-posthog: posthog.com
  • account-n8n: https://n8n.io
  • account-vaude: vaude.com
  • account-drooms: https://www.drooms.com

각 account_id는 API의 inputId가 됩니다. 결과가 입력 순서와 동일하게 도착한다고 보장할 수 없으므로 이 값이 중요합니다. 고정 ID를 사용하면 각 결과를 올바른 source account에 연결할 수 있습니다.

아래의 전체 스크립트를 find_linkedin_company_pages.py에 붙여 넣으세요.

python
import json
import os
import time
import uuid
import requests
def match_companies(accounts, api_key, matching_direction):
"""Submit one matching task, wait for it, and return every result."""
tasks_url = "https://api.datablist.com/v1/enrichments/tasks"
headers = {"X-API-Key": api_key}
inputs = [
{
"inputId": account["account_id"],
"data": {"sourceUrl": account["source_url"]},
}
for account in accounts
]
unique_id = str(uuid.uuid4())
print(f"Task uniqueId: {unique_id}", flush=True)
payload = {
"enrichmentId": "company-to-linkedin",
"uniqueId": unique_id,
"settings": {"matchingDirection": matching_direction},
"inputs": inputs,
}
response = requests.post(tasks_url, headers=headers, json=payload)
response.raise_for_status()
task = response.json()
task_id = task["@id"]
task_url = f"{tasks_url}/{task_id}"
while task["status"] not in ("completed", "failed", "stopped"):
time.sleep(3)
response = requests.get(task_url, headers=headers)
response.raise_for_status()
task = response.json()
if task["status"] != "completed":
raise RuntimeError(
f"Task {task_id} {task['status']}: {task.get('error')}"
)
results = []
results_url = f"{task_url}/results"
params = {"limit": 100}
while True:
response = requests.get(results_url, headers=headers, params=params)
response.raise_for_status()
page = response.json()
results.extend(page["results"])
next_cursor = page["nextCursor"]
if next_cursor is None:
break
params["cursor"] = next_cursor
return results
accounts = [
{
"account_id": "account-datablist",
"company_name": "Datablist",
"source_url": "datablist.com",
},
{
"account_id": "account-posthog",
"company_name": "PostHog",
"source_url": "posthog.com",
},
{
"account_id": "account-n8n",
"company_name": "n8n",
"source_url": "https://n8n.io",
},
{
"account_id": "account-vaude",
"company_name": "VAUDE",
"source_url": "vaude.com",
},
{
"account_id": "account-drooms",
"company_name": "Drooms",
"source_url": "https://www.drooms.com",
},
]
api_key = os.environ.get("DATABLIST_API_KEY")
if not api_key:
raise RuntimeError("Set DATABLIST_API_KEY before running this script.")
match_results = match_companies(
accounts, api_key, matching_direction="domain_to_linkedin"
)
print(json.dumps(match_results, indent=2))

다음 명령어로 실행합니다.

shell
python find_linkedin_company_pages.py

함수는 세 종류의 호출을 순서대로 실행합니다.

먼저 POST 요청은 matchingDirection을 domain_to_linkedin으로 설정하고 5개 웹사이트를 전송합니다. 매칭이 background task로 실행되기 때문에 API는 task ID와 함께 202 Accepted를 반환합니다. Requests 스크립트가 다음 단계로 넘어가기 전에 완료를 기다리므로 실행 흐름 자체는 순차적으로 보입니다.

python
response = requests.post(tasks_url, headers=headers, json=payload)
response.raise_for_status()
task = response.json()
task_id = task["@id"]

두 번째로 status 요청은 task가 completed, failed, stopped 중 하나가 될 때까지 상태를 확인합니다. 3초의 대기 시간을 두어 스크립트가 status 요청을 끊임없이 보내지 않도록 합니다.

세 번째로 results 요청은 한 페이지에서 최대 100개의 결과를 읽습니다. nextCursor에 값이 있으면 다음 요청의 cursor로 전달하며, nextCursor가 null일 때만 반복을 종료합니다.

매칭 결과와 검토 대상 확인하기

5개 input에 대한 전체 결과는 다음과 같습니다.

json
[
{
"inputId": "account-datablist",
"status": "success",
"outputs": {
"companyWebsite": "datablist.com",
"confidence": "high",
"companyLinkedInUrl": "https://www.linkedin.com/company/datablist",
"companyName": "datablist"
},
"creditsUsed": "1.5",
"error": null
},
{
"inputId": "account-posthog",
"status": "success",
"outputs": {
"companyWebsite": "posthog.com",
"confidence": "high",
"companyLinkedInUrl": "https://www.linkedin.com/company/posthog",
"companyName": "PostHog"
},
"creditsUsed": "1.5",
"error": null
},
{
"inputId": "account-n8n",
"status": "success",
"outputs": {
"companyWebsite": "n8n.io",
"confidence": "high",
"companyLinkedInUrl": "https://www.linkedin.com/company/n8n",
"companyName": "n8n"
},
"creditsUsed": "1.5",
"error": null
},
{
"inputId": "account-vaude",
"status": "success",
"outputs": {
"companyWebsite": "vaude.com",
"confidence": "high",
"companyLinkedInUrl": "https://www.linkedin.com/company/vaude",
"companyName": "vaude"
},
"creditsUsed": "1.5",
"error": null
},
{
"inputId": "account-drooms",
"status": "success",
"outputs": {
"companyWebsite": "drooms.com",
"confidence": "low",
"companyLinkedInUrl": "https://www.linkedin.com/company/drooms-software",
"companyName": "Drooms"
},
"creditsUsed": "1.5",
"error": null
}
]

status와 confidence는 별도로 확인해야 합니다. API는 실패한 input을 포함해 모든 input에 대한 결과 객체를 반환합니다. success status는 회사 페이지 후보를 찾았다는 뜻입니다. outputs.confidence 값은 웹사이트 매칭이 검증되었는지를 나타냅니다. inputId는 객체를 source account와 연결하고, creditsUsed는 해당 행에 청구된 credit을 기록하며, error에는 오류 발생 시 구조화된 실패 정보가 담깁니다.

첫 화면에 LinkedIn URL과 신뢰도만 필요하더라도 애플리케이션에는 전체 outputs 객체를 보관하세요. companyName과 companyWebsite가 있으면 수동 검토가 더 빨라집니다. 반환된 회사명의 대소문자가 다르거나 전체 URL을 입력했을 때 특히 유용합니다. 별도의 API 호출 없이도 필요한 맥락을 확보할 수 있습니다.

매칭 프로세스는 제출된 웹사이트를 정규화하고 회사 데이터셋에서 이미 알려진 웹사이트와 LinkedIn의 연결 관계를 확인하는 것으로 시작합니다. 그런 다음 입력 도메인과 LinkedIn 회사 페이지에 게시된 웹사이트를 비교합니다. 등록 도메인이 일치하면 high 신뢰도가 부여됩니다.

데이터셋에 LinkedIn URL이 없으면 회사 페이지 후보를 찾기 위한 Google 검색이 실행될 수 있습니다. 게시된 웹사이트와 대조해 검증할 수 없는 후보는 low 신뢰도로 반환될 수 있습니다. 웹사이트가 명확히 일치하지 않는 후보는 허용되지 않습니다.

신뢰도는 검토 지침으로 활용하세요. VAUDE는 https://www.linkedin.com/company/vaude와 함께 high 신뢰도를 반환했으므로 research 큐에 바로 넣을 수 있습니다. Drooms는 https://www.linkedin.com/company/drooms-software와 low 신뢰도를 반환했습니다. 이 관계를 사용하기 전에 Drooms 웹사이트와 LinkedIn 페이지를 직접 확인하세요.

Datablist, PostHog, n8n도 신뢰도 높은 매칭 결과를 반환했습니다. 이 API는 웹사이트와 회사 페이지의 연결 관계를 찾아줍니다. URL을 검토한 뒤 회사 규모, 업종 또는 기타 페이지 데이터가 필요하다면 다음 단계로 LinkedIn 회사 scraper API 가이드를 활용하세요.

결과로 Account 리서치 큐 만들기

이제 match_results를 재사용해 수동 회사 리서치를 위한 로컬 큐를 만듭니다. 아래 블록은 API를 다시 호출하지 않습니다. inputId를 기준으로 결과를 인덱싱한 다음 원래 account 목록을 순회하므로, 이후 특정 결과가 누락되더라도 모든 source account를 확인할 수 있습니다.

python
results_by_id = {result["inputId"]: result for result in match_results}
ready_for_research = []
needs_review = []
for account in accounts:
result = results_by_id.get(account["account_id"])
if result is not None:
outputs = result.get("outputs", {})
else:
outputs = {}
research_record = {
**account,
"companyLinkedInUrl": outputs.get("companyLinkedInUrl"),
"confidence": outputs.get("confidence"),
"api_result": result,
}
is_ready = (
result is not None
and result["status"] == "success"
and outputs.get("companyLinkedInUrl")
and outputs.get("confidence") == "high"
)
if is_ready:
ready_for_research.append(research_record)
else:
needs_review.append(research_record)
print("Ready for research:")
print(json.dumps(ready_for_research, indent=2))
print("Needs review:")
print(json.dumps(needs_review, indent=2))

결과 dictionary를 사용하면 응답 순서에 관계없이 데이터를 연결할 수 있습니다. account-vaude는 원본 vaude.com 레코드와 확인된 VAUDE 페이지를 연결한 뒤 ready_for_research에 들어갑니다. account-drooms는 전체 input URL과 API 결과를 그대로 유지하지만, result status가 success여도 신뢰도가 낮으므로 needs_review에 들어갑니다.

같은 로직을 적용하면 누락된 행, no_result 또는 error가 있는 행도 review 큐에 남습니다. 출력된 두 목록을 바탕으로 팀이 수동 회사 리서치를 명확하게 시작할 수 있습니다.

신뢰도 높은 LinkedIn 회사 페이지와 매칭된 VAUDE는 Ready for research로, 신뢰도가 낮은 Drooms는 Needs review로 분류된 화면
신뢰도 높은 LinkedIn 회사 페이지와 매칭된 VAUDE는 Ready for research로, 신뢰도가 낮은 Drooms는 Needs review로 분류된 화면

관리되는 동기식 Requests 예제도 다운로드할 수 있습니다. Repository에는 non-blocking HTTP가 필요한 애플리케이션을 위한 비동기 HTTPX 예제도 포함되어 있지만, 처음 연동한다면 위의 blocking 버전이 이해하기 더 쉽습니다.

LinkedIn 회사 페이지에서 웹사이트 역조회하기

매칭 방향을 바꾸면 같은 함수에 LinkedIn 회사 페이지를 입력할 수 있습니다. Source 목록에 회사 페이지 URL만 있고, 호환되는 회사 정보나 업무용 이메일 enrichment를 실행하기 전에 웹사이트가 필요할 때 유용합니다.

python
linkedin_accounts = [
{
"account_id": "account-datablist",
"company_name": "Datablist",
"source_url": "https://www.linkedin.com/company/datablist",
}
]
website_results = match_companies(
linkedin_accounts,
api_key,
matching_direction="linkedin_to_domain",
)

일반적인 LinkedIn 회사 페이지 조회에는 표준 매칭 요금이 적용됩니다. 숫자로 된 company ID와 Sales Navigator 회사 URL은 다른 역조회 경로를 사용하므로 10 credits가 필요할 수 있습니다. 이 방향을 no-code 방식으로 처리하려면 LinkedIn 회사 페이지에서 웹사이트 URL을 찾는 방법을 참고하세요.

웹사이트-LinkedIn 조회 Credit 계산하기

일반적인 웹사이트-LinkedIn 조회는 성공할 때마다 1.5 credits를 사용합니다. 따라서 위의 5개 매칭에는 총 7.5 credits가 사용되었습니다. 같은 요율로 1,000건을 성공적으로 매칭하면 1,500 credits가 필요합니다. 유효하지 않은 input이나 결과가 없는 행에는 credit이 차감되지 않을 수 있으므로, 실제 사용량은 각 결과의 creditsUsed 값을 확인하세요.

REST API 이용 권한은 Growth 플랜에 포함되며, 월 구독료와 top-up credit은 별도입니다. $20 top-up으로 20,000 credits를 받을 수 있으므로 credit당 비용은 $0.001입니다. 성공한 매칭 한 건에 1.5 credits가 사용되므로 1,000건을 매칭하면 $1.50 상당의 1,500 credits가 필요합니다. 최신 플랜과 패키지는 Datablist 요금제에서 확인하세요.

Loading pricing…

자주 발생하는 Input·Task·결과 문제 해결하기

  • DATABLIST_API_KEY가 없습니다: 스크립트가 요청을 전송하기 전에 중단됩니다. 환경 변수를 export한 뒤 명령어를 다시 실행하세요.
  • API가 Key를 거부합니다: Personal API Key를 복사했는지 확인하고 요청에서 X-API-Key에만 담아 전송했는지 점검하세요.
  • 지원되지 않는 input입니다: domain_to_linkedin에는 회사 웹사이트나 도메인을 사용하세요. 역방향 조회에는 개인 프로필이나 빈 값이 아닌, 지원되는 회사 페이지 URL을 입력해야 합니다.
  • Credit이 부족합니다: 잔액을 확인한 뒤 포함된 credit을 사용하거나 top-up을 추가한 다음 새 task를 생성하세요.
  • Task가 failed 또는 stopped 상태입니다: 다시 제출할지 결정하기 전에 task status, error, 기존 결과, credit 사용량을 확인하세요.
  • 결과의 신뢰도가 낮거나 no_result 또는 error입니다: source 웹사이트와 전체 결과를 needs_review에 보관하세요. 후보 페이지가 있다면 직접 열어 보고, 결과가 누락된 이유를 추측하지 마세요.

Task 생성 중 연결이 끊어졌다면 POST 요청 전에 출력된 uniqueId를 사용하세요. 다른 task를 만들기 전에 task 목록에서 해당 값을 찾습니다.

shell
curl --get "https://api.datablist.com/v1/enrichments/tasks" \
--header "X-API-Key: $DATABLIST_API_KEY" \
--data-urlencode "enrichmentId=company-to-linkedin" \
--data-urlencode "limit=100"

Task 목록은 uniqueId로 필터링할 수 없으므로 반환된 각 task를 확인하고, 필요하면 nextCursor를 따라가세요. 일치하는 값을 찾으면 해당 task의 @id를 스크립트와 동일한 status 및 results URL에 사용합니다.

하나의 task에는 최대 10,000개의 input을 담을 수 있습니다. 전체 요청, task 보관 기간, pagination 제한은 Company to LinkedIn API 문서에서 확인하세요.

다음 단계

이제 회사 웹사이트를 LinkedIn 회사 페이지 후보로 변환하는 재사용 가능한 Python Requests 함수를 갖추었습니다. 로컬 큐에서는 신뢰도 높은 매칭을 바로 리서치할 수 있도록 분류하고, 불확실하거나 실패한 레코드는 검토할 수 있게 그대로 남겨 둡니다.

5개의 예시를 소규모 account 목록으로 교체하고 신뢰도가 낮은 모든 후보를 검토하세요. 승인한 URL은 수동 회사 리서치에 활용하거나 LinkedIn company scraper API의 input으로 사용할 수 있습니다. Source 목록에 웹사이트 대신 회사명이 있다면 회사 웹사이트 finder API 가이드부터 시작하세요.