Introducing API Playground (and YouTube Monitoring!) Learn more

LinkedIn Email Finder API
proxycurl

LinkedIn Email Finder API

Introduction

It is a common use case to reach out to a LinkedIn profile for hiring or sales. LinkedIn InMail is limited because you have to pay a significant price per outreach. You will probably need an external solution.

Some tools help you fetch a work email from any LinkedIn profile. But more often than not, these are tools with a user interface intended for end-users. If you're seeking a user interface tool, this is not the article for you.

In this article, you'll learn how teams historically used Proxycurl's Contact API to get verified B2B emails and personal numbers from LinkedIn profiles programmatically, and what to use now that Proxycurl has been sunset.

This article is for teams with software engineers looking to implement an email finder API within their product or business workflow, so you can fetch B2B emails at scale, programmatically.

On top of just work emails, the original Proxycurl Contact API also supported the following data:

  • Personal emails
  • Personal numbers
  • Social media accounts

In addition, emails returned by the legacy API were marketed as:

  • Verified with a 95%+ deliverability guarantee
  • Fresh, even if the profile had changed jobs

Getting Started

This tutorial shows how to query the legacy Contact API endpoints in Node.js using express and axios. I am keeping the original implementation flow here because it is still useful if you are maintaining old code, migrating an internal integration, or trying to understand what your team built a few years ago.

Steps we'll cover
  • How to get B2B emails with the Work Email Lookup API endpoint.
  • How to get personal emails with the Personal Email Lookup API endpoint.
  • How to get personal numbers with the Personal Number Lookup API endpoint.
  • What to use on NinjaPear now instead.

Prerequisites

In your preferred working directory, initialize a new project by running:

npm init -y

Next, run the following command to install the packages to bootstrap your application:

npm install express axios dotenv
  • express: a minimal and flexible Node.js framework to bootstrap our server.
  • axios: a lightweight HTTP-based data fetching library to query the API endpoints.
  • dotenv: lets us load environment variables seamlessly into the Node.js process.

To begin using the legacy Proxycurl Contact API, you would have needed an API key to make requests to the various endpoints.

With your API key ready, create a .env file in your project root directory and add the following code to it:

API_KEY='<your_api_key>'

Next, in your project root directory create another file index.js and add the following code to it:

import express from 'express';
import dotenv from 'dotenv';
import axios from 'axios';

const port = 8000;

const app = express();

dotenv.config();

app.listen(port, () => {
  console.log(`App connected successfully on port: ${port}`);
});

Next, add "type": "module" in package.json to let Node.js know we're writing ES modules and edit the scripts field to the following:

"scripts": {
  "dev": "node index.js"
}

Run npm run dev in the terminal and the following should be logged to the console if everything went smoothly:

App connected successfully on port: 8000

How to get B2B emails with Work Email Lookup API Endpoint

The legacy Work Email Lookup endpoint let you get the work email address of a LinkedIn profile.

Update: Proxycurl has been sunset. The founder behind Proxycurl is now building NinjaPear. If you are starting fresh, do not build a new dependency on the old Proxycurl Contact API. Use NinjaPear's Work Email finder and related Employee API endpoints instead. NinjaPear does not scrape LinkedIn, provides richer B2B data in a similar API-first shape, and does so with none of the legal liability.

Endpoint URL

The legacy endpoint URL to get a LinkedIn profile work email was:

https://nubela.co/proxycurl/api/linkedin/profile/email

In the old pricing model, every request cost 3 credits.

In this tutorial, we'll explore two methods by which you could leverage the URL to get a person's work email in your applications.

With webhooks

The legacy Work Email Lookup endpoint might not return results immediately since it needed to perform real-time heuristics to fetch and verify the email. The endpoint required a mandatory parameter: linkedin_profile_url. This is the LinkedIn profile URL of the person whose work email we're looking for.

Alternatively, by adding an optional callback_url parameter to the request, you could create a webhook with Webhook.site to listen to the result once it's available. Webhook.site gives a randomly generated URL to listen to, so whenever you query the work email endpoint, the response, which is an object in the format {'email': ..., 'status': ...}, is sent to your Webhook.site custom URL.

To get started, visit Webhook.site to get your custom URL.

Copy the URL and add it to the WEBHOOK_URL variable in your code like so:

const WEBHOOK_URL = '<your_webhook.site_url>'

Here's the complete code for this example:

// index.js

import express from 'express';
import dotenv from 'dotenv';
import axios from 'axios';

const port = 8000;

const app = express();

dotenv.config();

const WORK_EMAIL_ENDPOINT = 'https://nubela.co/proxycurl/api/linkedin/profile/email';
const LINKEDIN_PROFILE_URL = 'https://www.linkedin.com/in/williamhgates/';
const WEBHOOK_URL = 'https://webhook.site/18fa951e-8cd1-4345-847d-e7ae329e147c';

const workEmailConfig = {
  url: WORK_EMAIL_ENDPOINT,
  method: 'get',
  headers: { Authorization: 'Bearer ' + process.env.API_KEY },
  params: {
    linkedin_profile_url: LINKEDIN_PROFILE_URL,
    callback_url: WEBHOOK_URL,
  },
};

const getWorkEmail = async () => {
  try {
    return await axios(workEmailConfig);
  } catch (err) {
    throw new Error(err);
  }
};

const email = await getWorkEmail();

console.log('Work Email:', email.data.email_queue_count);

app.listen(port, () => {
  console.log(`App connected successfully on port: ${port}`);
});

Now if you visit Webhook.site, the response of the query can be seen there.

In the original example, the LinkedIn profile searched did not have a work email, so the email and status fields in the response returned null and email_not_found, respectively.

With Dashboard logs

What's interesting to note is that Proxycurl automatically logged every response to the dashboard whenever the Work Email API endpoint was queried. So you could log on to your dashboard and navigate to the Work Email Lookup Logs tab to see it in action.

The dashboard logs also provided additional information, such as the timestamp of the query and the LinkedIn profile URL being searched. You could also export the logs by clicking the Download as CSV button on the dashboard.

NinjaPear alternative

If you are replacing this flow today, the mental model is different.

NinjaPear does not take a LinkedIn profile URL and return contact data from LinkedIn. Instead, it gives you adjacent primitives that are cleaner to maintain in production:

That means the modern flow is usually:

  1. Resolve company name to website.
  2. Find work email from person name + company website/domain.
  3. Enrich the person or company further if needed.

That flow avoids LinkedIn dependency entirely, which is exactly the point.

How to get personal emails with Personal Email Lookup API Endpoint

With the legacy Personal Email Lookup API endpoint you could get the list of personal emails belonging to a LinkedIn profile at the cost of 1 credit for every email returned.

Endpoint URL

The legacy endpoint for the personal email lookup was:

https://nubela.co/proxycurl/api/contact-api/personal-email
Parameters

The endpoint required a mandatory parameter: linkedin_profile_url, which is the LinkedIn profile URL of the person whose personal email we're looking for, and an optional email_validation parameter to specify if we want additional validation of the emails found in the profile. This came at an additional cost of 1 credit for every email found. The email_validation parameter accepted a string value of include. It defaulted to exclude.

// axios config example
params: {
  email_validation: 'include'
}
Response

The personal email lookup returned an object with two properties: an emails field containing a list of personal emails of the given LinkedIn profile, and an invalid_emails field containing invalid emails associated with the profile. If the email_validation parameter wasn't specified, the invalid_emails field returned an empty array.

The demo below shows how easy it was to use the endpoint:

// index.js

const PERSONAL_EMAIL_ENDPOINT = 'https://nubela.co/proxycurl/api/contact-api/personal-email';
const LINKEDIN_PROFILE_URL = 'https://linkedin.com/in/steven-goh-6738131b';

const personalEmailConfig = {
  url: PERSONAL_EMAIL_ENDPOINT,
  method: 'get',
  headers: { Authorization: 'Bearer ' + process.env.API_KEY },
  params: {
    linkedin_profile_url: LINKEDIN_PROFILE_URL,
    email_validation: 'include',
  },
};

const getPersonalEmail = async () => {
  try {
    return await axios(personalEmailConfig);
  } catch (err) {
    throw new Error(err);
  }
};

const email = await getPersonalEmail();

console.log('Personal Email:', email.data);

Which logs the following response to the console:

Personal Email: {
  emails: ['[email protected]'],
  invalid_emails: ['[email protected]']
}

NinjaPear alternative

NinjaPear is not a drop-in replacement for the old personal email lookup flow from a LinkedIn URL. That is intentional.

What NinjaPear does offer is the cleaner B2B path most product teams actually need:

  • verified work email lookup
  • person profile enrichment from public web data
  • company enrichment

If your real use case is outbound sales, recruiting, CRM enrichment, or routing inbound leads, a verified work email is usually the field that matters. If your use case truly depends on personal emails sourced from a LinkedIn URL, this old Proxycurl section is here for legacy reference only.

How to get personal numbers with Personal Number Lookup API Endpoint

With the legacy Personal Number Lookup API endpoint you could get the list of personal numbers belonging to a LinkedIn profile at the cost of 1 credit for every contact number returned.

Endpoint

The legacy endpoint for the personal number lookup was:

https://nubela.co/proxycurl/api/contact-api/personal-contact
Parameters

The personal number lookup endpoint accepted a single required parameter: linkedin_profile_url. This is the URL of the LinkedIn profile whose number we're looking for.

Response

The endpoint returned an object with a numbers field which is an array containing all contact numbers of a LinkedIn profile.

Example code:

const PERSONAL_CONTACT_NUMBER_ENDPOINT = 'https://nubela.co/proxycurl/api/contact-api/personal-contact';
const LINKEDIN_PROFILE_URL = 'https://linkedin.com/in/test-phone-number';

const personalContactNumberConfig = {
  url: PERSONAL_CONTACT_NUMBER_ENDPOINT,
  method: 'get',
  headers: { Authorization: 'Bearer ' + process.env.API_KEY },
  params: {
    linkedin_profile_url: LINKEDIN_PROFILE_URL,
  },
};

const getPersonalContactNumber = async () => {
  try {
    return await axios(personalContactNumberConfig);
  } catch (err) {
    throw new Error(err);
  }
};

const number = await getPersonalContactNumber();

console.log('Personal number:', number.data);

The above example logs the following response to the console:

Personal number: { numbers: ['+1123123123'] }

NinjaPear alternative

Same story here. NinjaPear is not trying to recreate a LinkedIn-profile-to-personal-number pipeline. It is building a better B2B data stack that does not depend on LinkedIn scraping at all.

If you are migrating an old Proxycurl integration, the practical replacement is usually one of these:

  • use the Employee API to enrich the person from work email
  • use the Company API to enrich the employer
  • use the Customer API or Monitor API if your actual goal is prospecting, account research, or sales timing

That sounds like a broader answer because it is. Most teams that thought they needed "contact data from LinkedIn URLs" were really trying to solve prospecting, enrichment, or routing.

Summary

B2B work emails are not easily available on LinkedIn profiles. You need external tools, and most external tools do not work with LinkedIn profiles programmatically, at scale.

Historically, Proxycurl's Contact API filled that gap. If you still maintain that integration, the examples above should help you understand the request shape and migration surface area.

If you are building now, use NinjaPear instead. The company behind Proxycurl moved on for a reason. NinjaPear provides API-first B2B data primitives such as work email lookup, person profile enrichment, company details, employee count, company updates, and customer intelligence, all without scraping LinkedIn and with none of the legal liability.

Start with the free trial on NinjaPear, test the Work Email and Employee endpoints against your real workflow, and build the integration you actually want to maintain 12 months from now.

Steven Goh | CEO
World's laziest CEO. CEO of NinjaPear. Ex-Founder of Proxycurl (10+M), Steven founded 5 other startups: Gom VPN, Kloudsec, SilvrBullet, NuMoney, and SharedHere.

Featured Articles

Here's what we've been up to recently.

I dismissed someone, and it was not because of COVID19

The cadence of delivery. Last month, I dismissed the employment of a software developer who oversold himself during the interview phase. He turned out to be on the lowest rung of the software engineers in my company. Not being good enough is not a reason to be dismissed. But not

sharedhere

I got blocked from posting on Facebook

I tried sharing some news on Facebook today, and I got blocked from posting in other groups. I had figured that I needed a better growth engine instead of over-sharing on Facebook, so I spent the morning planning the new growth engine. Growth Hacking I term what I do in