@lineai/linkedin-api
Version:
Professional LinkedIn API client with TypeScript support, entity classes, and developer-friendly features. Perfect for AI coders, recruiting, lead generation, market research, and content analysis. Includes comprehensive JSDoc, helper constants (LOCATIONS
1,936 lines (1,809 loc) • 80.7 kB
JavaScript
import axios from "axios";
/**
* LinkedIn Data API - Real Endpoints Documentation
* Base URL: https://linkedin-data-api.p.rapidapi.com
*
* Headers Required:
* - X-RapidAPI-Key: Your RapidAPI key
* - X-RapidAPI-Host: linkedin-data-api.p.rapidapi.com
*/
export const ENDPOINTS = {
// BASE URL: https://linkedin-data-api.p.rapidapi.com
// PROFILE APIS - Complete documentation based on actual RapidAPI documentation
get_profile_data: {
path: "/",
method: "GET",
description: "Get comprehensive LinkedIn profile data",
parameters: {
required: ["username"],
optional: [],
},
example_params: {
username: "jaywestlin",
},
},
// get_profile_data_by_url: {
// path: "/get-profile-data-by-url",
// method: "GET",
// description: "Get profile data using LinkedIn profile URL",
// parameters: {
// required: ["url"],
// optional: [],
// },
// example_params: {
// url: "https://www.linkedin.com/in/jaywestlin/",
// },
// },
search_people: {
path: "/search-people",
method: "GET",
description: "Search for LinkedIn profiles with various filters",
parameters: {
required: [],
optional: [
"keywords",
"start",
"geo",
"schoolId",
"firstName",
"lastName",
"keywordSchool",
"keywordTitle",
"company",
],
},
example_params: {
keywords: "max",
start: "0",
geo: "103644278,101165590",
schoolId: "",
firstName: "",
lastName: "",
keywordSchool: "",
keywordTitle: "",
company: "",
},
notes: {
start: "Could be one of these: 0, 10, 20, 30, etc.",
geo: "Follow the location ID guide link in the documentation",
company: "Company name",
},
},
search_people_by_url: {
path: "/search-people-by-url",
method: "POST",
description: "Search people using LinkedIn search URL parameters",
parameters: {
required: [],
optional: [],
},
body_params: {
required: ["url"],
optional: [],
},
example_body: {
url: "https://www.linkedin.com/search/results/people/?currentCompany=%5B%221035%22%5D&geoUrn=%5B%22103644278%22%5D&keywords=max&origin=FACETED_SEARCH&sid=%3AB5",
},
content_type: "application/json",
},
get_profile_recent_activity_time: {
path: "/get-profile-recent-activity-time",
method: "GET",
description: "Get recent activity timestamp for a profile",
parameters: {
required: ["username"],
optional: [],
},
example_params: {
username: "jaywestlin",
},
},
get_profile_posts: {
path: "/get-profile-posts",
method: "GET",
description: "Get posts from a LinkedIn profile",
parameters: {
required: ["username"],
optional: ["start", "paginationToken", "postedAt"],
},
example_params: {
username: "jaywestlin",
start: "", // "use this param to get posts in next results page: 0 for page 1, 50 for page 2 100 for page 3, etc."
paginationToken: "", // "required when fetching the next results page. The token from the previous call must be used."
postedAt: "", // "filters posts after fetching them from LinkedIn and returns posts that are newer than the given date. Example value: 2024-01-01 00:00"
},
},
get_profile_post_and_comments: {
path: "/get-profile-post-and-comments",
method: "GET",
description: "Get specific post and its comments",
parameters: {
required: ["urn"],
optional: [],
},
example_params: {
urn: "7181285108586211378",
},
},
get_profile_post_comment: {
path: "/get-profile-posts-comments",
method: "GET",
description: "Get comments for a specific post",
parameters: {
required: ["urn", "sort"],
optional: ["page", "paginationToken"],
},
example_params: {
urn: "7169084130104737792",
sort: "mostRelevant", // mostRelevant, mostRecent
page: "1",
paginationToken: "", // required when fetching next results page
},
},
get_profiles_comments: {
path: "/get-profiles-comments",
method: "GET",
description: "Get all comments made by a profile",
parameters: {
required: ["username"],
// optional: ["start", "count"],
},
example_params: {
username: "jaywestlin",
// start: "0",
// count: "10",
},
},
get_profile_connection_and_follower_count: {
path: "/get-profile-connection-and-follower-count",
method: "GET",
description: "Get profile connection and follower counts",
parameters: {
required: ["username"],
optional: [],
},
example_params: {
username: "jaywestlin",
},
},
get_profile_data_and_connection_and_follower_count: {
path: "/data-connection-count",
method: "GET",
description: "Get profile data along with connection and follower counts",
parameters: {
required: ["username"],
optional: [],
},
example_params: {
username: "jaywestlin",
},
},
get_received_recommendations: {
path: "/get-received-recommendations",
method: "GET",
description: "Get recommendations received by a profile",
parameters: {
required: ["username"],
optional: ["start"],
},
example_params: {
username: "jaywestlin",
start: "0",
},
},
get_given_recommendations: {
path: "/get-given-recommendations",
method: "GET",
description: "Get recommendations given by a profile",
parameters: {
required: ["username"],
optional: ["start"],
},
example_params: {
username: "jaywestlin",
start: "0",
},
},
get_profile_likes: {
path: "/get-profile-likes",
method: "GET",
description: "Get reactions on profile posts",
parameters: {
required: ["username"],
optional: ["start", "paginationToken"],
},
example_params: {
username: "jaywestlin",
start: "",
paginationToken: "",
},
},
about_this_profile: {
path: "/about-this-profile",
method: "GET",
description: "Get profile about section",
parameters: {
required: ["username"],
optional: [],
},
example_params: {
username: "jaywestlin",
},
},
get_profile_data_connection_count_posts: {
path: "/profile-data-connection-count-posts",
method: "GET",
description: "Get comprehensive profile data with connections and posts",
parameters: {
required: ["username"],
optional: [],
},
example_params: {
username: "jaywestlin",
},
},
profile_data_and_recommendations: {
path: "/all-profile-data",
method: "GET",
description: "Get profile data with recommendations",
parameters: {
required: ["username"],
optional: [],
},
example_params: {
username: "jaywestlin",
},
},
get_similar_profiles: {
path: "/similar-profiles",
method: "GET",
description: "Get profiles similar to the specified profile",
parameters: {
required: ["url"],
optional: [],
},
example_params: {
url: "https://www.linkedin.com/in/jaywestlin/",
},
},
// get_profile_positions_with_skills: {
// path: "/get-profile-positions-with-skills",
// method: "GET",
// description: "Get profile work positions with associated skills",
// parameters: {
// required: ["username"],
// optional: [],
// },
// example_params: {
// username: "jaywestlin",
// },
// },
get_profile_top_position: {
path: "/profile/positions/top",
method: "GET",
description: "Get the top/current position of a profile",
parameters: {
required: ["username"],
optional: [],
},
example_params: {
username: "jaywestlin",
},
},
// get_profile_company_interest: {
// path: "/profiles/interests/companies",
// method: "POST",
// description: "Get companies a profile is interested in",
// parameters: {
// required: [],
// optional: [],
// },
// body_params: {
// required: ["username", "page"],
// optional: [],
// },
// example_body: {
// username: "jaywestlin",
// page: 1,
// },
// content_type: "application/json",
// },
// get_profile_top_voice_interests: {
// path: "/profiles/interests/top-voices",
// method: "POST",
// description: "Get top voice interests for a profile",
// parameters: {
// required: [],
// optional: [],
// },
// body_params: {
// required: ["username", "page"],
// optional: [],
// },
// example_body: {
// username: "jaywestlin",
// page: 1,
// },
// content_type: "application/json",
// },
get_profile_group_interests: {
path: "/profiles/interests/groups",
method: "POST",
description: "Get group interests for a profile",
parameters: {
required: [],
optional: [],
},
body_params: {
required: ["username", "page"],
optional: [],
},
example_body: {
username: "jaywestlin",
page: 1,
},
content_type: "application/json",
},
get_profile_school_interests: {
path: "/profiles/interests/schools",
method: "POST",
description: "Get school interests for a profile",
parameters: {
required: [],
optional: [],
},
body_params: {
required: ["username", "page"],
optional: [],
},
example_body: {
username: "jaywestlin",
page: 1,
},
content_type: "application/json",
},
get_profile_newsletter_interests: {
path: "/profiles/interests/newsletters",
method: "POST",
description: "Get newsletter interests for a profile",
parameters: {
required: [],
optional: [],
},
body_params: {
required: ["username", "page"],
optional: [],
},
example_body: {
username: "jaywestlin",
page: 1,
},
content_type: "application/json",
},
get_company_details: {
path: "/get-company-details",
method: "GET",
description: "Get detailed information about a LinkedIn company",
parameters: {
required: ["username"],
optional: [],
},
example_params: {
username: "google",
// include_employees: true,
// include_posts: false,
// include_jobs: true,
},
},
get_company_details_by_id: {
path: "/get-company-details-by-id",
method: "GET",
description: "Get company details using LinkedIn company ID",
parameters: {
required: ["id"],
optional: [],
},
example_params: {
company_id: "1441",
// include_insights: true,
// include_updates: false,
},
},
search_companies: {
path: "/companies/search",
method: "POST",
description: "Search for LinkedIn companies with filters",
parameters: {
required: ["keyword"],
optional: ["locations", "industries", "companySizes", "hasJobs", "page"],
},
body_params: {
required: [],
optional: [
"keyword",
"locations",
"companySizes",
"hasJobs",
"industries",
"page",
],
},
example_params: {
keyword: "",
locations: [103644278],
industries: [96, 4],
companySizes: ["D", "E", "F", "G"],
hasJobs: true,
page: 1,
},
notes: `Possible company sizes
B: 1-10 employees
C: 11-50 employees
D: 51-200 employees
E: 201-500 employees
F: 501-1000 employees
G: 1001-5000 employees
H: 5001-10,000 employees
I: 10,001+ employees`,
},
get_company_jobs: {
path: "/company-jobs",
method: "POST",
description: "Get job postings from a specific company",
body_params: {
required: ["companyIds"],
optional: ["page", "sort"],
},
example_params: {
companyIds: [5383240, 2382910],
page: 1,
sort: "mostRecent",
},
},
get_company_by_domain: {
path: "/get-company-by-domain",
method: "GET",
description: "Get company information using company domain/website",
parameters: {
required: ["domain"],
},
example_params: {
domain: "apple.com",
},
},
// get_company_insights: {
// path: "/get-company-insights",
// method: "GET",
// description: "Get premium company insights and analytics (premium feature)",
// parameters: {
// required: ["username"],
// },
// example_params: {
// username: "amazon",
// },
// },
get_company_employees_count: {
path: "/get-company-employees-count",
method: "POST",
description: "Get employee count and statistics for a company",
parameters: {
required: ["companyId"],
optional: ["locations"],
},
example_params: {
companyId: "1441", // Google company ID
locations: [], // Optional array of location IDs to filter employees by location
},
},
get_company_jobs_count: {
path: "/get-company-jobs-count",
method: "GET",
description: "Get the total number of active job postings for a company",
parameters: {
required: ["companyId"],
},
example_params: {
companyId: "1441", // Google company ID
},
},
get_company_pages_people_also_viewed: {
path: "/get-company-pages-people-also-viewed",
method: "GET",
description:
"Get companies that people also viewed when looking at this company",
parameters: {
required: ["username"],
},
example_params: {
username: "google",
},
},
get_company_posts: {
path: "/get-company-posts",
method: "GET",
description: "Get posts published by a company",
parameters: {
required: ["username"],
optional: ["start", "paginationToken"],
},
example_params: {
username: "google",
start: 0,
paginationToken: "", // options, Use this for pagination, e.g., "AQH1..."
},
},
get_company_post_comments: {
path: "/get-company-post-comments",
method: "GET",
description: "Get comments on a specific company post",
parameters: {
required: ["urn"],
optional: ["sort", "page"],
},
example_params: {
urn: "7179144327430844416",
sort: "mostRelevant",
page: 50,
},
},
// search_jobs: {
// path: "/search-jobs",
// method: "GET",
// description: "Search for LinkedIn job postings with comprehensive filters",
// parameters: {
// required: ["keywords"],
// optional: ["locationId", "companyIds", "datePosted", "salary", "jobType", "experienceLevel", "titleIds", "functionIds", "start", "industryIds", "onsiteRemote", "sort"],
// },
// example_params: {
// keywords: "golang",
// locationId: "92000000", // Default: 92000000, follow link to find location id
// companyIds: "", // follow link to find company id
// datePosted: "anyTime", // anyTime, pastMonth, pastWeek, past24Hours
// salary: "", // 40k+, 60k+, 80k+, 100k+, 120k+, 140k+, 160k+, 180k+, 200k+ (example: 80k+)
// jobType: "", // fullTime, partTime, contract, internship (example: contract)
// experienceLevel: "", // internship, associate, director, entryLevel, midSeniorLevel, executive (example: executive)
// titleIds: "", // follow link to find title id by title
// functionIds: "", // follow link to find function id
// start: "", // 0, 25, 50, 75, 100, etc. Maximum start is 975
// industryIds: "", // follow link to find industry id
// onsiteRemote: "", // onSite, remote, hybrid (example: remote)
// sort: "mostRelevant", // mostRelevant, mostRecent
// },
// },
// get_job_details: {
// path: "/get-job-details",
// method: "GET",
// description: "Get detailed information about a specific job posting",
// parameters: {
// required: ["jobId"],
// optional: [],
// },
// example_params: {
// jobId: "3472345678",
// },
// },
//
// search_jobs_v2: {
// path: "/search-jobs-v2",
// method: "GET",
// description: "Enhanced job search with additional filters and improved results",
// parameters: {
// required: ["keywords"],
// optional: [], // Need to check specific params for V2
// },
// example_params: {
// keywords: "data",
// },
// },
//
// get_hiring_team: {
// path: "/get-hiring-team",
// method: "GET",
// description: "Get information about the hiring team for a specific job",
// parameters: {
// required: ["jobId"],
// optional: [],
// },
// example_params: {
// jobId: "3472345678",
// },
// },
//
// get_profiles_posted_jobs: {
// path: "/get-profiles-posted-jobs",
// method: "GET",
// description: "Get jobs posted by a specific LinkedIn profile/recruiter",
// parameters: {
// required: ["username"],
// optional: [],
// },
// example_params: {
// username: "jaywestlin",
// },
// },
search_posts: {
path: "/search-posts",
method: "POST",
description: "Search for LinkedIn posts with advanced filters",
parameters: {
required: [],
optional: [],
},
body_params: {
required: ["keyword"],
optional: [
"sortBy",
"datePosted",
"page",
"contentType",
"fromMember",
"mentionsMember",
"fromCompany",
"mentionsOrganization",
"authorIndustry",
"authorCompany",
"authorTitle",
],
},
example_body: {
keyword: "microsoft",
sortBy: "date_posted", // date_posted, relevance
datePosted: "", // date filter
page: 1,
contentType: "", // post type filter
fromMember: [
"ACoAAAEkwwAB9KEc2TrQgOLEQ-vzRyZeCDyc6DQ",
"ACoAAANuWM8BtmA18VYdgqPtIWt6GhBCTDXToV4",
],
mentionsMember: ["ACoAAAEkwwAB9KEc2TrQgOLEQ-vzRyZeCDyc6DQ"],
fromCompany: [1441, 1035],
mentionsOrganization: [1441, 1035],
authorIndustry: [96, 4],
authorCompany: [1035],
authorTitle: "",
},
content_type: "application/json",
},
search_post_by_hashtag: {
path: "/search-posts-by-hashtag",
method: "POST",
description: "Search for posts that contain specific hashtags",
parameters: {
required: [],
optional: [],
},
body_params: {
required: ["hashtag"],
optional: ["sortBy", "start", "paginationToken"],
},
example_body: {
hashtag: "golang",
sortBy: "REV_CHRON", // RELEVANCE, REV_CHRON
start: "0", // for pagination: 0, 50, 100, 150, 200, 250, etc.
paginationToken: "", // required when fetching next results page
},
content_type: "application/json",
},
get_post_by_id: {
path: "/get-post",
method: "GET",
description: "Get detailed information about a specific LinkedIn post",
parameters: {
required: ["postId"],
optional: [],
},
example_params: {
postId: "7134567890123456789",
},
},
get_post_by_url: {
path: "/get-post",
method: "GET",
description: "Get detailed information about a specific LinkedIn post",
parameters: {
required: ["url"],
optional: [],
},
example_params: {
url: "https://www.linkedin.com/feed/update/urn:li:activity:7219434359085252608/",
},
},
get_post_reposts: {
path: "/get-post-reposts",
method: "POST",
description: "Get all reposts/shares of a specific LinkedIn post",
parameters: {
required: [],
optional: [],
},
body_params: {
required: ["urn"],
optional: ["page", "paginationToken"],
},
example_body: {
urn: "7245786832909557760",
page: 1,
paginationToken: "",
},
content_type: "application/json",
},
get_post_reactions: {
path: "/get-post-reactions",
method: "POST",
description:
"Get reactions (likes, appreciation, empathy) for a specific post",
body_params: {
required: ["url"],
optional: [
"page",
"reactionType", // LIKE, APPRECIATION, EMPATHY, INTEREST, PRAISE, ENTERTAINMENT
],
},
example_body: {
url: "7134567890123456789",
page: 1, // for pagination: 0, 50, 100, etc.
reactionType: "like", // like, love, celebrate, support, insightful, funny
},
content_type: "application/json",
},
// get_user_articles: {
// path: "/get-user-articles",
// method: "GET",
// description: "Get all articles published by a specific LinkedIn user",
// parameters: {
// optional: ["url", "username"],
// },
// example_params: {
// url: "https://www.linkedin.com/in/williamhgates",
// username: "williamhgates",
// },
// },
// get_article: {
// path: "/get-article",
// method: "GET",
// description: "Get detailed information about a specific LinkedIn article",
// parameters: {
// required: ["url"],
// },
// example_params: {
// url: "https://www.linkedin.com/pulse/hidden-costs-unreliable-electricity-bill-gates/",
// },
// },
// get_article_comments: {
// path: "/get-article-comments",
// method: "GET",
// description: "Get comments on a specific LinkedIn article",
// parameters: {
// required: ["url"],
// optional: ["page", "sort"],
// },
// example_params: {
// url: "https://www.linkedin.com/pulse/2024-corporate-climate-pivot-bill-gates-u89mc/?trackingId=V85mkekwT9KruOXln2gzIg%3D%3D",
// page: 0,
// sort: "REVERSE_CHRONOLOGICAL",
// },
// },
// get_article_reactions: {
// path: "/get-article-reactions",
// method: "GET",
// description: "Get reactions (likes, comments, shares) for a specific article",
// parameters: {
// required: ["url"],
// optional: ["page"],
// },
// example_params: {
// url: "https://www.linkedin.com/pulse/2024-corporate-climate-pivot-bill-gates-u89mc/?trackingId=V85mkekwT9KruOXln2gzIg%3D%3D",
// page: "like",
// },
// },
search_locations: {
path: "/search-locations",
method: "GET",
description: "Search for LinkedIn locations with filters",
parameters: {
required: ["keyword"],
},
example_params: {
keyword: "berlin",
},
},
};
// Helper Constants
export const LOCATIONS = {
US: {
ALL: 103644278,
NEW_YORK: 105080838,
SAN_FRANCISCO: 102277331,
LOS_ANGELES: 102448103,
CHICAGO: 103112676,
BOSTON: 102380872,
SEATTLE: 104116203,
AUSTIN: 104472866,
DENVER: 103736294,
MIAMI: 105149290,
},
};
export const COMPANY_SIZES = {
SELF_EMPLOYED: "A",
TINY: "B",
SMALL: "C",
MEDIUM: "D",
LARGE: "E",
XLARGE: "F",
ENTERPRISE: "G",
MASSIVE: "H",
MEGA: "I",
ALL: ["A", "B", "C", "D", "E", "F", "G", "H", "I"],
};
export const INDUSTRIES = {
TECHNOLOGY: 96,
FINANCIAL_SERVICES: 43,
HEALTHCARE: 14,
RETAIL: 27,
MANUFACTURING: 12,
EDUCATION: 69,
CONSTRUCTION: 48,
REAL_ESTATE: 44,
ENTERTAINMENT: 28,
CONSULTING: 9,
};
// Default values
export const DEFAULT_PROFILE_PICTURE =
"https://cdn.linkedin.com/default-profile.png";
// Error Classes
/**
* Base error class for all LinkedIn API related errors
* @class LinkedInError
* @extends Error
* @example
* try {
* await api.getProfile('invalid-user');
* } catch (error) {
* if (error instanceof LinkedInError) {
* console.log('LinkedIn API Error:', error.message);
* console.log('Error Code:', error.code);
* }
* }
*/
export class LinkedInError extends Error {
constructor(message, code) {
super(message);
this.code = code;
this.name = "LinkedInError";
}
}
/**
* Error thrown when API rate limits are exceeded
* @class RateLimitError
* @extends LinkedInError
* @example
* try {
* await api.searchProfiles({ keywords: 'test' });
* } catch (error) {
* if (error instanceof RateLimitError) {
* console.log('Rate limited. Retry after:', error.retryAfter);
* }
* }
*/
export class RateLimitError extends LinkedInError {
constructor(message, headers) {
super(message, "RATE_LIMIT");
this.retryAfter = headers["x-ratelimit-reset"]
? new Date(headers["x-ratelimit-reset"] * 1000)
: null;
}
}
/**
* Error thrown when requested resource is not found or inaccessible
* @class NotFoundError
* @extends LinkedInError
* @example
* try {
* await api.getProfile('nonexistent-user');
* } catch (error) {
* if (error instanceof NotFoundError) {
* console.log('Profile not found or private');
* }
* }
*/
export class NotFoundError extends LinkedInError {
constructor(message) {
super(message, "NOT_FOUND");
}
}
/**
* Error thrown when network requests fail
* @class NetworkError
* @extends LinkedInError
* @example
* try {
* await api.getProfile('user');
* } catch (error) {
* if (error instanceof NetworkError) {
* console.log('Network error:', error.originalError.message);
* }
* }
*/
export class NetworkError extends LinkedInError {
constructor(message, originalError) {
super(message, "NETWORK_ERROR");
this.originalError = originalError;
}
}
// Helper Functions
/**
* Validate if a username meets LinkedIn's format requirements
* @param {string} username - The username to validate
* @returns {boolean} True if the username is valid
* @example
* isValidUsername('john-doe'); // true
* isValidUsername('john@doe'); // false
*/
export function isValidUsername(username) {
return /^[a-zA-Z0-9-]{3,100}$/.test(username);
}
/**
* Extract username from a LinkedIn profile URL
* @param {string} url - LinkedIn profile URL
* @returns {string|null} The extracted username or null if not found
* @example
* extractUsername('https://linkedin.com/in/john-doe'); // 'john-doe'
* extractUsername('https://example.com'); // null
*/
export function extractUsername(url) {
const match = url.match(/linkedin\.com\/in\/([a-zA-Z0-9-]+)/);
return match?.[1] || null;
}
// Entity Classes
/**
* LinkedIn Profile entity with helper methods for accessing profile data
* @class LinkedInProfile
* @example
* const profile = await api.getProfile('satyanadella');
* console.log(profile.getFullName()); // "Satya Nadella"
* console.log(profile.getCurrentPosition()?.title); // "CEO"
*/
export class LinkedInProfile {
/**
* Create a LinkedInProfile instance
* @param {ProfileData} data - Raw profile data from LinkedIn API
*/
constructor(data) {
this.data = data;
}
/**
* Get raw profile data for advanced use cases
* @returns {ProfileData} Original API response data
*/
get raw() {
return this.data;
}
/**
* Get profile ID
* @returns {number} Profile ID
*/
getId() {
return this.data.id;
}
/**
* Get profile URN (Uniform Resource Name)
* @returns {string} Profile URN
*/
getUrn() {
return this.data.urn;
}
/**
* Get LinkedIn username
* @returns {string} Username from profile URL
*/
getUsername() {
return this.data.username;
}
/**
* Get first name
* @returns {string} First name or empty string if not available
*/
getFirstName() {
return this.data.firstName || "";
}
/**
* Get last name
* @returns {string} Last name or empty string if not available
*/
getLastName() {
return this.data.lastName || "";
}
/**
* Get full display name
* @returns {string} Combined first and last name, or 'Unknown' if neither available
* @example
* profile.getFullName(); // "Satya Nadella"
*/
getFullName() {
return `${this.getFirstName()} ${this.getLastName()}`.trim() || "Unknown";
}
/**
* Get professional headline
* @returns {string} Professional headline or empty string
* @example
* profile.getHeadline(); // "CEO at Microsoft"
*/
getHeadline() {
return this.data.headline || "";
}
/**
* Get profile summary/about section
* @returns {string} Profile summary or empty string
*/
getSummary() {
return this.data.summary || "";
}
/**
* Get LinkedIn profile URL
* @returns {string} Full LinkedIn profile URL
* @example
* profile.getLinkedInUrl(); // "https://linkedin.com/in/satyanadella"
*/
getLinkedInUrl() {
return `https://linkedin.com/in/${this.data.username}`;
}
/**
* Check if profile is marked as Top Voice
* @returns {boolean} True if profile has Top Voice status
*/
isTopVoice() {
return this.data.isTopVoice || false;
}
/**
* Check if profile is a LinkedIn Creator
* @returns {boolean} True if profile has Creator status
*/
isCreator() {
return this.data.isCreator || false;
}
/**
* Check if profile has Premium membership
* @returns {boolean} True if profile has Premium status
*/
isPremium() {
return this.data.isPremium || false;
}
/**
* Get profile picture URL
* @returns {string} Profile picture URL or default avatar if none available
* @example
* profile.getProfilePictureUrl('large'); // High resolution image
*/
getProfilePictureUrl() {
const url = this.data.profilePicture;
if (!url) return DEFAULT_PROFILE_PICTURE;
return url;
}
/**
* Get background/cover image URL
* @returns {string|null} Background image URL or null if not available
*/
getBackgroundImageUrl() {
const images = this.data.backgroundImage;
if (!images || images.length === 0) return null;
return images[images.length - 1].url;
}
/**
* Get location information
* @returns {Object} Location object with country, city, full, and countryCode
* @example
* const location = profile.getLocation();
* console.log(location.city); // "Seattle"
* console.log(location.country); // "United States"
*/
getLocation() {
return (
this.data.geo || {
country: "",
city: "",
full: "",
countryCode: "",
}
);
}
/**
* Get current/most recent position
* @returns {Object|null} Position object or null if no positions available
* @example
* const position = profile.getCurrentPosition();
* if (position) {
* console.log(position.title); // "CEO"
* console.log(position.companyName); // "Microsoft"
* }
*/
getCurrentPosition() {
return this.data.position?.[0] || null;
}
/**
* Get all work positions/experience
* @returns {Array} Array of position objects, empty array if none
* @example
* const positions = profile.getAllPositions();
* positions.forEach(pos => console.log(pos.title, 'at', pos.companyName));
*/
getAllPositions() {
return this.data.position || [];
}
/**
* Get education history
* @returns {Array} Array of education objects, empty array if none
* @example
* const education = profile.getEducation();
* education.forEach(edu => console.log(edu.degree, 'from', edu.schoolName));
*/
getEducation() {
return this.data.educations || [];
}
/**
* Get all skills
* @returns {Array} Array of skill objects, empty array if none
* @example
* const skills = profile.getSkills();
* skills.forEach(skill => console.log(skill.name, skill.endorsementsCount));
*/
getSkills() {
return this.data.skills || [];
}
/**
* Get skills that have endorsements
* @returns {Array} Array of skill objects with endorsements > 0
* @example
* const endorsedSkills = profile.getSkillsWithEndorsements();
* console.log(`${endorsedSkills.length} skills with endorsements`);
*/
getSkillsWithEndorsements() {
return this.getSkills().filter((skill) => skill.endorsementsCount > 0);
}
}
/**
* LinkedIn Company entity with helper methods for accessing company data
* @class LinkedInCompany
* @example
* const company = await api.getCompany('microsoft');
* console.log(company.getName()); // "Microsoft"
* console.log(company.getEmployeeCount()); // 221000
*/
export class LinkedInCompany {
/**
* Create a LinkedInCompany instance
* @param {CompanyData} data - Raw company data from LinkedIn API
*/
constructor(data) {
this.data = data;
}
/**
* Get raw company data for advanced use cases
* @returns {CompanyData} Original API response data
*/
get raw() {
return this.data;
}
/**
* Get company ID
* @returns {string} Company ID
*/
getId() {
return this.data.id;
}
/**
* Get company name (falls back to universal name if main name unavailable)
* @returns {string} Company name or 'Unknown Company' if neither available
* @example
* company.getName(); // "Microsoft"
*/
getName() {
return this.data.name || this.data.universalName || "Unknown Company";
}
/**
* Get universal company name (URL-friendly identifier)
* @returns {string} Universal name or empty string
* @example
* company.getUniversalName(); // "microsoft"
*/
getUniversalName() {
return this.data.universalName || "";
}
/**
* Get LinkedIn company page URL
* @returns {string} Full LinkedIn company URL
* @example
* company.getLinkedInUrl(); // "https://linkedin.com/company/microsoft"
*/
getLinkedInUrl() {
return this.data.linkedinUrl || "";
}
/**
* Get company tagline/slogan
* @returns {string} Company tagline or empty string
* @example
* company.getTagline(); // "Empowering every person and organization on the planet to achieve more"
*/
getTagline() {
return this.data.tagline || "";
}
/**
* Get company description
* @returns {string} Company description or empty string
*/
getDescription() {
return this.data.description || "";
}
/**
* Get company website URL
* @returns {string} Website URL or empty string
* @example
* company.getWebsite(); // "https://microsoft.com"
*/
getWebsite() {
return this.data.website || "";
}
/**
* Get company phone number
* @returns {string} Phone number or empty string
*/
getPhone() {
return this.data.phone || "";
}
/**
* Get total employee count
* @returns {number} Number of employees, 0 if not available
* @example
* company.getEmployeeCount(); // 221000
*/
getEmployeeCount() {
return this.data.staffCount || 0;
}
/**
* Get LinkedIn follower count
* @returns {number} Number of followers, 0 if not available
* @example
* company.getFollowerCount(); // 15000000
*/
getFollowerCount() {
return this.data.followerCount || 0;
}
/**
* Get employee count range (e.g., "10001+")
* @returns {string} Staff count range or empty string
* @example
* company.getStaffCountRange(); // "10001+"
*/
getStaffCountRange() {
return this.data.staffCountRange || "";
}
/**
* Get company logo URL
* @param {string} [size='medium'] - Logo size ('small', 'medium', 'large')
* @returns {string} Logo URL or empty string if not available
* @example
* company.getLogoUrl('large'); // High resolution logo
*/
getLogoUrl(size = "medium") {
const sizeMap = { small: 100, medium: 200, large: 400 };
const targetSize = sizeMap[size] || 200;
const logo = this.data.logos?.find((l) => l.width === targetSize);
return logo?.url || this.data.Images?.logo || "";
}
/**
* Get company cover/background image URL
* @returns {string|null} Cover image URL or null if not available
*/
getCoverImageUrl() {
return this.data.Images?.cover || null;
}
/**
* Get headquarters location
* @returns {Object|null} Headquarters location object or null if not available
* @example
* const hq = company.getHeadquarters();
* if (hq) {
* console.log(hq.city); // "Redmond"
* console.log(hq.country); // "US"
* }
*/
getHeadquarters() {
return this.data.locations?.find((loc) => loc.headquarter) || null;
}
/**
* Get all company locations/offices
* @returns {Array} Array of location objects, empty array if none
* @example
* const locations = company.getAllLocations();
* locations.forEach(loc => console.log(loc.city, loc.country));
*/
getAllLocations() {
return this.data.locations || [];
}
/**
* Get company industries
* @returns {Array} Array of industry strings, empty array if none
* @example
* company.getIndustries(); // ["Software Development", "Computer Software"]
*/
getIndustries() {
return this.data.industries || [];
}
/**
* Get company specialties/focus areas
* @returns {Array} Array of specialty strings, empty array if none
* @example
* company.getSpecialties(); // ["cloud computing", "productivity software", "business applications"]
*/
getSpecialties() {
return this.data.specialities || [];
}
/**
* Get company founding year
* @returns {number|null} Founding year or null if not available
* @example
* company.getFounded(); // 1975
*/
getFounded() {
return this.data.founded || null;
}
/**
* Check if company page is verified by LinkedIn
* @returns {boolean} True if verified
*/
isVerified() {
return this.data.pageVerification?.verified || false;
}
/**
* Check if company page is claimed (controlled by the company)
* @returns {boolean} True if claimed
*/
isClaimed() {
return !this.data.isClaimable;
}
}
/**
* LinkedIn Post entity with helper methods for accessing post data and engagement metrics
* @class LinkedInPost
* @example
* const post = await api.getPost('7219434359085252608');
* console.log(post.getText()); // Post content
* console.log(post.getTotalEngagement()); // 1523
*/
export class LinkedInPost {
/**
* Create a LinkedInPost instance
* @param {PostData} data - Raw post data from LinkedIn API
*/
constructor(data) {
this.data = data;
}
/**
* Get raw post data for advanced use cases
* @returns {PostData} Original API response data
*/
get raw() {
return this.data;
}
/**
* Get post URN (Uniform Resource Name)
* @returns {string} Post URN identifier
*/
getUrn() {
return this.data.urn;
}
/**
* Get post text content
* @returns {string} Post text or empty string if not available
* @example
* post.getText(); // "Excited to announce our new product launch!"
*/
getText() {
return this.data.text || "";
}
/**
* Get LinkedIn post URL
* @returns {string} Full LinkedIn post URL or empty string
* @example
* post.getLinkedInUrl(); // "https://www.linkedin.com/posts/..."
*/
getLinkedInUrl() {
return this.data.shareUrl || "";
}
/**
* Get shareable post URL (same as getLinkedInUrl)
* @returns {string} Post share URL or empty string
*/
getShareUrl() {
return this.data.shareUrl || "";
}
/**
* Get post creation date as Date object
* @returns {Date} Date when post was created
* @example
* const date = post.getPostedAt();
* console.log(date.toLocaleDateString()); // "7/17/2024"
*/
getPostedAt() {
return new Date(this.data.postedDateTimestamp);
}
/**
* Get post creation timestamp
* @returns {number} Unix timestamp in milliseconds
*/
getPostedDateTimestamp() {
return this.data.postedDateTimestamp;
}
/**
* Get total engagement (reactions + comments + reposts)
* @returns {number} Combined engagement count
* @example
* post.getTotalEngagement(); // 1523 (sum of all interactions)
*/
getTotalEngagement() {
return (
(this.data.totalReactionCount || 0) +
(this.data.commentsCount || 0) +
(this.data.repostsCount || 0)
);
}
/**
* Get total reaction count (all types of reactions)
* @returns {number} Total reactions, 0 if not available
* @example
* post.getTotalReactionCount(); // 107
*/
getTotalReactionCount() {
return this.data.totalReactionCount || 0;
}
/**
* Get like count specifically
* @returns {number} Number of likes, 0 if not available
* @example
* post.getLikeCount(); // 89
*/
getLikeCount() {
return this.data.likeCount || 0;
}
/**
* Get comments count
* @returns {number} Number of comments, 0 if not available
* @example
* post.getCommentsCount(); // 23
*/
getCommentsCount() {
return this.data.commentsCount || 0;
}
/**
* Get reposts/shares count
* @returns {number} Number of reposts, 0 if not available
* @example
* post.getRepostsCount(); // 15
*/
getRepostsCount() {
return this.data.repostsCount || 0;
}
/**
* Get post author information
* @returns {Object} Author object with name, headline, etc.
* @example
* const author = post.getAuthor();
* console.log(author.firstName, author.lastName); // "John Doe"
*/
getAuthor() {
return this.data.author || {};
}
/**
* Get company information if posted by a company
* @returns {Object} Company object or empty object if not a company post
*/
getCompany() {
return this.data.company || {};
}
/**
* Check if post contains video content
* @returns {boolean} True if post has video
* @example
* if (post.hasVideo()) {
* const video = post.getVideo();
* console.log(video.duration); // Video length in seconds
* }
*/
hasVideo() {
return !!this.data.video?.url;
}
/**
* Check if post contains article content
* @returns {boolean} True if post has article
* @example
* if (post.hasArticle()) {
* const article = post.getArticle();
* console.log(article.title); // Article title
* }
*/
hasArticle() {
return !!this.data.article?.title;
}
/**
* Check if post contains document attachments
* @returns {boolean} True if post has documents
*/
hasDocument() {
return !!this.data.document;
}
/**
* Check if post is a poll
* @returns {boolean} True if post is a poll
*/
isPoll() {
return !!this.data.poll;
}
/**
* Check if this post is a repost/share of another post
* @returns {boolean} True if this is a repost
*/
isRepost() {
return !!this.data.reposted || !!this.data.resharedPost;
}
/**
* Check if post is a brand partnership
* @returns {boolean} True if marked as brand partnership
*/
isBrandPartnership() {
return this.data.isBrandPartnership || false;
}
/**
* Get video content details
* @returns {Object|null} Video object with URL, duration, etc. or null if no video
* @example
* const video = post.getVideo();
* if (video) {
* console.log(video.url); // Video URL
* console.log(video.duration); // Duration in seconds
* }
*/
getVideo() {
return this.data.video || null;
}
/**
* Get article content details
* @returns {Object|null} Article object with title, link, etc. or null if no article
* @example
* const article = post.getArticle();
* if (article) {
* console.log(article.title); // Article title
* console.log(article.link); // Article URL
* }
*/
getArticle() {
return this.data.article || null;
}
}
// Search Item Classes removed in v1.3.2 - Search results now return raw data objects directly
// Search Result Classes
/**
* Profile search results with pagination support
* @class ProfileSearchResult
* @example
* const results = await api.searchProfiles({ keywords: 'engineer' });
* console.log(`Found ${results.total} profiles`);
* results.items.forEach(item => console.log(item.getFullName()));
*
* if (results.hasNextPage()) {
* const page2 = await results.getNextPage();
* }
*/
export class ProfileSearchResult {
/**
* Create a ProfileSearchResult instance
* @param {ProfileSearchData} data - Search result data from API
* @param {LinkedInAPI} api - API instance for pagination
* @param {ProfileSearchParams} searchParams - Original search parameters
*/
constructor(data, api, searchParams) {
this._data = data;
this.api = api;
this.searchParams = { ...searchParams }; // Defensive copy to prevent external mutation
}
/**
* Get the data object (for advanced use cases)
* @returns {ProfileSearchData} Search result data
*/
get data() {
return { ...this._data }; // Return copy to prevent mutation
}
/**
* Get search parameters used for this search
* @returns {ProfileSearchParams} Search parameters
*/
get params() {
return { ...this.searchParams }; // Return copy to prevent mutation
}
/**
* Get total number of profiles found
* @returns {number} Total profile count
* @example
* console.log(`Found ${results.total} profiles`); // "Found 1000 profiles"
*/
get total() {
return this._data.total || 0;
}
/**
* Get array of profile search items
* @returns {ProfileSearchItemData[]} Array of profile search data objects
* @example
* results.items.forEach(item => {
* console.log(item.fullName, '-', item.headline);
* });
*/
get items() {
// Use flattened data structure
const items = this._data.items || [];
if (!Array.isArray(items)) {
console.warn(
"ProfileSearchResult data does not contain items array:",
this._data,
);
return [];
}
return items; // Return raw data objects directly in v1.3.2+
}
/**
* Check if more results are available
* @returns {boolean} True if more pages available
* @example
* if (results.hasNextPage()) {
* console.log('More results available');
* }
*/
hasNextPage() {
return this.items.length > 0 && this.items.length < this.total;
}
/**
* Get the next page of search results
* @returns {Promise<ProfileSearchResult>} Next page of results
* @throws {Error} When no more pages available
* @example
* const page2 = await results.getNextPage();
* console.log(`Page 2 has ${page2.items.length} items`);
*/
async getNextPage() {
if (!this.hasNextPage()) {
throw new Error("No more pages available");
}
const nextPage = (this.searchParams.page || 1) + 1;
return this.api.searchProfiles({
...this.searchParams,
page: nextPage,
});
}
}
/**
* Company search results with pagination support
* @class CompanySearchResult
*/
export class CompanySearchResult {
/**
* Create a CompanySearchResult instance
* @param {CompanySearchData} data - Search result data from API
* @param {LinkedInAPI} api - API instance for pagination
* @param {CompanySearchParams} searchParams - Original search parameters
*/
constructor(data, api, searchParams) {
this._data = data;
this.api = api;
this.searchParams = { ...searchParams }; // Defensive copy to prevent external mutation
}
/**
* Get the data object (for advanced use cases)
* @returns {CompanySearchData} Search result data
*/
get data() {
return { ...this._data }; // Return copy to prevent mutation
}
/**
* Get search parameters used for this search
* @returns {CompanySearchParams} Search parameters
*/
get params() {
return { ...this.searchParams }; // Return copy to prevent mutation
}
/**
* Get total number of companies found
* @returns {number} Total company count
*/
get total() {
return this._data.total || 0;
}
/**
* Get array of company search items
* @returns {CompanySearchItemData[]} Array of company search data objects
*/
get items() {
// Use flattened data structure
const items = this._data.items || [];
if (!Array.isArray(items)) {
console.warn(
"CompanySearchResult data does not contain items array:",
this._data,
);
return [];
}
// Transform universalName to username for consistency with profiles (v1.3.3+)
return items.map(item => ({
...item,
username: item.universalName,
universalName: undefined,
}));
}
/**
* Check if more results are available
* @returns {boolean} True if more pages available
*/
hasNextPage() {
return this.items.length > 0;
}
/**
* Get the next page of search results
* @returns {Promise<CompanySearchResult>} Next page of results
* @throws {Error} When no more pages available
*/
async getNextPage() {
if (!this.hasNextPage()) {
throw new Error("No more pages available");
}
const nextPage = (this.searchParams.page || 1) + 1;
return this.api.searchCompanies({
...this.searchParams,
page: nextPage,
});
}
}
/**
* Post search results with pagination support
* @class PostSearchResult
*/
export class PostSearchResult {
/**
* Create a PostSearchResult instance
* @param {PostSearchData} data - Search result data from API
* @param {LinkedInAPI} api - API instance for pagination
* @param {PostSearchParams} searchParams - Original search parameters
*/
constructor(data, api, searchParams) {
this._data = data;
this.api = api;
this.searchParams = { ...searchParams }; // Defensive copy to prevent external mutation
}
/**
* Get the data object (for advanced use cases)
* @returns {PostSearchData} Search result data
*/
get data() {
return { ...this._data }; // Return copy to prevent mutation
}
/**
* Get search parameters used for this search
* @returns {PostSearchParams} Search parameters
*/
get params() {
return { ...this.searchParams }; // Return copy to prevent mutation
}
/**
* Get total number of posts found
* @returns {number} Total post count
*/
get total() {
return this._data.total || 0;
}
/**
* Get number of posts in current page (calculated from items.length)
* @returns {number} Current page count
*/
get count() {
return this._data.items?.length || 0;
}
/**
* Get array of post search items
* @returns {PostSearchItemData[]} Array of post search data objects
*/
get items