You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP โ†’
Socket
Book a DemoInstallSign in
Socket

@lineai/linkedin-api

Package Overview
Dependencies
Maintainers
1
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@lineai/linkedin-api

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.3.8
latest
Source
npmnpm
Version published
Maintainers
1
Created
Source

@lineai/linkedin-api

Professional LinkedIn API client with TypeScript support, entity classes, and developer-friendly features. Implements the LinkedIn Data API from RapidAPI.

Quick Reference

OperationMethodPurposeKey ParametersReturns
Profile SearchsearchProfiles(params)Find profiles by criteriakeywords, geo, company, minItemsProfileSearchResult
Profile GetgetProfile(username)Full profile datausernameLinkedInProfile
Company SearchsearchCompanies(params)Find companies by criteriakeywords, industries, companySizes, minItemsCompanySearchResult
Company GetgetCompany(username)Full company datausernameLinkedInCompany
Post SearchsearchPosts(params)Find posts by criteriakeywords, author, datePosted, minItemsPostSearchResult
Post GetgetPost(postId)Full post datapostIdLinkedInPost

Essential Imports

import LinkedInAPI, { 
  LOCATIONS, 
  INDUSTRIES, 
  COMPANY_SIZES,
  LinkedInError,
  RateLimitError,
  NotFoundError 
} from '@lineai/linkedin-api';

Core Entity Methods

EntityKey MethodsReturns
LinkedInProfilegetFullName(), getHeadline(), getCurrentPosition(), getLinkedInUrl()Formatted strings/objects
LinkedInCompanygetName(), getFollowerCount(), getEmployeeCount(), getLinkedInUrl()Company data
LinkedInPostgetText(), getLikeCount(), getCommentCount(), getAuthor()Post metrics

๐Ÿ†• What's New in v1.3.8

  • ๐Ÿ” Improved TypeScript Types - Added PostSearchItemAuthorData interface for better type safety when working with post search results
  • ๐ŸŽฏ Enhanced IntelliSense - Post search author data now has proper autocompletion and type checking
  • ๐Ÿ› ๏ธ Type Safety Fix - Eliminates type mismatches between post search results and full post data author schemas

v1.3.7 Features

  • ๐Ÿ”ง Next.js Build Fix - Fixed webpack compilation error by replacing process.env.NODE_ENV manipulation with instance-based debug mode
  • โšก Better Debug Mode - Debug logging now uses instance property instead of environment variable modification

v1.3.6 Features

  • ๐Ÿ“ฆ Package Optimization - Removed examples directory to reduce package size and improve build compatibility
  • ๐Ÿ› ๏ธ Build Fixes - Resolved Next.js build issues by streamlining package structure

v1.3.5 Features

  • ๐Ÿงน Dependency Cleanup - Removed Prettier and related ESLint configurations to reduce package size and simplify development
  • โšก Streamlined Build - Cleaner development environment with fewer dependencies

v1.3.4 Features

  • ๐Ÿ› ๏ธ Data Transformation Fix - Fixed company search universalName โ†’ username transformation to occur in CompanySearchResult.items getter for better data consistency
  • ๐ŸŽฏ Unified API Experience - Both api.getProfile(item.username) and api.getCompany(item.username) now use the same field name

v1.3.3 Features

  • ๐Ÿ”„ Consistent Username Field - Company search results now use username instead of universalName for consistency with profile search

v1.3.2 Features

  • ๐Ÿ—‘๏ธ Simplified Search Results - Removed ProfileSearchItem, CompanySearchItem, and PostSearchItem wrapper classes for direct data access
  • ๐ŸŽฏ Direct Data Access - Search results now return raw data objects with helper methods for cleaner, simpler usage

v1.3.1 Features

  • ๐Ÿ”ง Fixed Location Parameter Types - LocationId is now correctly typed as number instead of string
  • โœ… API Compatibility - Location constants (LOCATIONS) now properly work with LinkedIn API requirements
  • ๐ŸŽฏ Cross-Method Consistency - Both profile search (GET) and company search (POST) handle location arrays correctly

v1.3.0 Features

  • โœจ Enhanced Type Safety - Complete TypeScript response type definitions prevent runtime errors
  • ๐Ÿ”’ Immutable Parameters - Search parameters are never mutated, ensuring predictable behavior
  • ๐ŸŽ๏ธ Improved Caching - Now works for all get methods with 100% cache hit performance
  • ๐Ÿ› ๏ธ Better Error Handling - More specific error types with better debugging information
  • ๐ŸŽฏ Unified API - Consistent pagination and parameter handling across all search methods
  • ๐Ÿ” Enhanced Debugging - Improved debug logs with accurate response structure information

Features

  • ๐Ÿš€ Easy to use - Simple, intuitive API with high-level methods
  • ๐Ÿ“˜ TypeScript ready - Full type definitions included
  • ๐ŸŽฏ Entity classes - Clean data access without dealing with raw JSON
  • ๐Ÿ”„ Seamless data loading - Load full profiles/companies/posts from search results
  • ๐Ÿ›ก๏ธ Safe defaults - Never worry about null/undefined values
  • โšก Built-in caching - Reduce API calls automatically (v1.3.0+)
  • ๐ŸŽ›๏ธ Pagination helpers - Easy navigation through search results
  • ๐Ÿท๏ธ Helper constants - No more magic strings for locations, industries, etc.
  • ๐Ÿ”’ Parameter immutability - Original search params never modified (v1.3.0+)

Installation

npm install @lineai/linkedin-api
# or
yarn add @lineai/linkedin-api

Quick Start

import { LinkedInAPI } from '@lineai/linkedin-api';

const api = new LinkedInAPI('your-rapidapi-key');

// Get a profile
const profile = await api.getProfile('satyanadella');
console.log(profile.getFullName()); // "Satya Nadella"
console.log(profile.getCurrentPosition()?.title); // "CEO"

Usage Examples

Profile Operations

import { LinkedInAPI, LOCATIONS } from '@lineai/linkedin-api';

const api = new LinkedInAPI('your-rapidapi-key');

// Search for profiles
const searchResults = await api.searchProfiles({
  keywords: 'software engineer',
  geo: [LOCATIONS.US.SAN_FRANCISCO, LOCATIONS.US.NEW_YORK], // Auto-joined
  company: 'Google'
});

console.log(`Found ${searchResults.total} profiles`);

// Access search results
searchResults.items.forEach(item => {
  console.log(item.getFullName());
  console.log(item.getHeadline());
  console.log(item.getLinkedInUrl());
});

// Get full profile using username from search result
const firstResult = searchResults.items[0];
const fullProfile = await api.getProfile(firstResult.username);

// Access full profile data
console.log(fullProfile.getFullName());
console.log(fullProfile.getCurrentPosition()?.companyName);
console.log(fullProfile.getEducation()[0]?.schoolName);
console.log(fullProfile.getSkills().length);
console.log(fullProfile.getProfilePictureUrl('large'));

// Direct profile access
const profile = await api.getProfile('billgates');
console.log(profile.getLinkedInUrl()); // https://linkedin.com/in/billgates

Company Operations

import { LinkedInAPI, COMPANY_SIZES, INDUSTRIES, LOCATIONS } from '@lineai/linkedin-api';

const api = new LinkedInAPI('your-rapidapi-key');

// Search companies
const companies = await api.searchCompanies({
  keyword: 'artificial intelligence',
  locations: [LOCATIONS.US.ALL],
  industries: [INDUSTRIES.TECHNOLOGY],
  companySizes: [COMPANY_SIZES.LARGE, COMPANY_SIZES.XLARGE], // 201-1000 employees
  hasJobs: true
});

// Access company data
const company = companies.items[0];
console.log(company.getName());
console.log(company.getTagline());

// Get full company details using username from search result
const fullCompany = await api.getCompany(company.username);
console.log(fullCompany.getEmployeeCount());
console.log(fullCompany.getHeadquarters()?.city);
console.log(fullCompany.getSpecialties());
console.log(fullCompany.getFollowerCount());
console.log(fullCompany.getWebsite());

// Direct company access
const microsoft = await api.getCompany('microsoft');
console.log(microsoft.getName()); // "Microsoft"
console.log(microsoft.getEmployeeCount());
console.log(microsoft.getAllLocations().length);

Post Operations

const api = new LinkedInAPI('your-rapidapi-key');

// Search posts
const posts = await api.searchPosts({
  keyword: 'machine learning',
  sortBy: 'date_posted',
  fromCompany: [1441] // Google's company ID
});

console.log(`Found ${posts.total} posts`);

// Access post data
const post = posts.items[0];
console.log(post.getText());
console.log(post.getAuthorName());
console.log(post.getPostedAt());

// Get full post details using URN from search result
const fullPost = await api.getPost(post.urn);
console.log(fullPost.getTotalEngagement());
console.log(fullPost.getLikeCount());
console.log(fullPost.getCommentsCount());
console.log(fullPost.hasVideo());
console.log(fullPost.getArticle()?.title);

// Direct post access
const specificPost = await api.getPost('7219434359085252608');
console.log(specificPost.getAuthor().firstName);
console.log(specificPost.getTotalEngagement());

Pagination

// Handle pagination easily
const results = await api.searchProfiles({ keywords: 'CEO' });

console.log(`Page 1: ${results.items.length} items`);

if (results.hasNextPage()) {
  const page2 = await results.getNextPage();
  console.log(`Page 2: ${page2.items.length} items`);
}

// Process all pages
let currentPage = results;
let pageNum = 1;

while (currentPage.items.length > 0) {
  console.log(`Processing page ${pageNum}: ${currentPage.items.length} items`);
  
  // Process items
  for (const item of currentPage.items) {
    console.log(item.getFullName());
  }
  
  if (currentPage.hasNextPage()) {
    currentPage = await currentPage.getNextPage();
    pageNum++;
  } else {
    break;
  }
}

Error Handling

import { LinkedInAPI, NotFoundError, RateLimitError } from '@lineai/linkedin-api';

const api = new LinkedInAPI('your-rapidapi-key');

try {
  const profile = await api.getProfile('invalid-username-xyz');
} catch (error) {
  if (error instanceof NotFoundError) {
    console.error('Profile not found');
  } else if (error instanceof RateLimitError) {
    console.error(`Rate limited. Retry after: ${error.retryAfter}`);
  } else {
    console.error('Unexpected error:', error.message);
  }
}

TypeScript Support

import { 
  LinkedInAPI, 
  LinkedInProfile, 
  LinkedInCompany,
  ProfileSearchParams,
  LOCATIONS,
  LocationId 
} from '@lineai/linkedin-api';

const api = new LinkedInAPI('your-key');

// Full type safety
const searchParams: ProfileSearchParams = {
  keywords: 'engineer',
  geo: [LOCATIONS.US.SEATTLE] as LocationId[]
};

const results = await api.searchProfiles(searchParams);

// TypeScript knows all available methods
const profile: LinkedInProfile = await api.getProfile('username');
const position = profile.getCurrentPosition(); // Type: Position | null

if (position) {
  console.log(position.title); // TypeScript knows all Position properties
  console.log(position.companyName);
}

Helper Constants

import { LOCATIONS, COMPANY_SIZES, INDUSTRIES } from '@lineai/linkedin-api';

// Use location constants instead of numeric IDs
const usProfiles = await api.searchProfiles({
  geo: [LOCATIONS.US.ALL]
});

const techCompanies = await api.searchCompanies({
  locations: [
    LOCATIONS.US.SAN_FRANCISCO,
    LOCATIONS.US.SEATTLE,
    LOCATIONS.US.AUSTIN
  ],
  industries: [INDUSTRIES.TECHNOLOGY],
  companySizes: COMPANY_SIZES.ALL // All company sizes
});

๐Ÿ†• Smart Retry with minItems (v1.2.2)

All search methods now support intelligent retry logic to ensure you get the results you need:

Profile Search with minItems

// Get at least 15 profiles - will retry across different pages until found
const profiles = await api.searchProfiles({
  keywords: 'software engineer',
  geo: [LOCATIONS.US.SAN_FRANCISCO],
  minItems: 15,     // Minimum results required
  maxRetries: 5     // Maximum retry attempts
});

console.log(`Found ${profiles.items.length} profiles`); // At least 15

Company Search with minItems

// Get substantial company dataset
const companies = await api.searchCompanies({
  keywords: 'fintech startup',
  industries: [INDUSTRIES.FINANCIAL_SERVICES],
  minItems: 20,     // Keep retrying until 20+ companies found
  maxRetries: 6
});

Post Search with minItems

// Collect many posts for content analysis
const posts = await api.searchPosts({
  keywords: 'artificial intelligence',
  datePosted: 'past-week',
  minItems: 25,     // Need at least 25 posts
  maxRetries: 8
});

Disable Retry Logic

// For exact pagination control, disable retries
const exactPage = await api.searchProfiles({
  keywords: 'manager',
  start: '20',
  minItems: 0       // Disable retries - return exact page results
});

Why use minItems?

  • LinkedIn has many private profiles/companies that appear in counts but don't return data
  • Results can be sparse across different pages
  • Perfect for data collection, analysis, or when you need substantial sample sizes
  • Automatically handles pagination gaps and empty result pages

Advanced Usage

// Access raw data when needed
const profile = await api.getProfile('username');
console.log(profile.raw); // Original API response

// Use the low-level endpoint method
const response = await api.callEndpoint('get_profile_posts', {
  username: 'satyanadella',
  start: '0'
});

// Cache management
api.clearCache(); // Clear all cached data
api.enableCache = false; // Disable caching

// Batch operations
const usernames = ['billgates', 'satyanadella', 'sundarpichai'];
const profiles = await Promise.all(
  usernames.map(username => api.getProfile(username))
);

profiles.forEach(profile => {
  console.log(`${profile.getFullName()} - ${profile.getHeadline()}`);
});

API Reference

Main Class: LinkedInAPI

const api = new LinkedInAPI(rapidApiKey, rapidApiHost?)
MethodParametersReturnsDescription
searchProfiles(params){keywords?, geo?, company?, start?, minItems?, maxRetries?}ProfileSearchResultSearch LinkedIn profiles with smart retry
getProfile(username)stringLinkedInProfileGet full profile data
searchCompanies(params){keywords?, industries?, companySizes?, minItems?, maxRetries?}CompanySearchResultSearch LinkedIn companies with smart retry
getCompany(username)stringLinkedInCompanyGet full company data
searchPosts(params){keywords?, author?, datePosted?, minItems?, maxRetries?}PostSearchResultSearch LinkedIn posts with smart retry
getPost(postId)stringLinkedInPostGet full post data
clearCache()-voidClear all cached data
validateParameters(endpoint, params)string, objectValidationResultValidate parameters

Entity Classes

LinkedInProfile

MethodReturnsDescription
getFullName()stringCombined first + last name
getHeadline()stringProfessional headline
getCurrentPosition()Position | nullCurrent job position
getAllPositions()Position[]All work experience
getEducation()Education[]Education history
getSkills()Skill[]Skills list
getLinkedInUrl()stringFull LinkedIn profile URL
getLocation()LocationGeographic location
getProfilePictureUrl(size?)stringProfile picture URL

LinkedInCompany

MethodReturnsDescription
getName()stringCompany name
getFollowerCount()numberLinkedIn followers
getEmployeeCount()numberEmployee count
getLinkedInUrl()stringFull LinkedIn company URL
getDescription()stringCompany description
getSpecialties()string[]Company specialties
getIndustries()string[]Industry categories
getWebsite()stringCompany website

LinkedInPost

MethodReturnsDescription
getText()stringPost content text
getLikeCount()numberNumber of likes
getCommentCount()numberNumber of comments
getShareCount()numberNumber of shares
getAuthor()AuthorPost author info
getPostedAt()DatePost publication date
getTotalEngagement()numberTotal engagement count
hasMedia()booleanContains images/videos

Search Results Classes

All search result classes support pagination:

MethodReturnsDescription
hasNextPage()booleanMore results available
getNextPage()Promise<SearchResult>Fetch next page
itemsSearchItem[]Current page items
totalnumberTotal result count

Search Item Data

Search results return raw data objects. Use the API methods to get full details:

// Get full data from search results
const profiles = await api.searchProfiles({ keywords: 'engineer' });
const fullProfile = await api.getProfile(profiles.items[0].username);

const companies = await api.searchCompanies({ keyword: 'tech' });
const fullCompany = await api.getCompany(companies.items[0].username);

const posts = await api.searchPosts({ keyword: 'AI' });
const fullPost = await api.getPost(posts.items[0].urn);

Error Types

ErrorWhen ThrownPropertiesExample Handling
LinkedInErrorBase error classmessage, codeGeneric error handling
RateLimitErrorRate limit exceededretryAfter (Date)Wait until retry time
NotFoundErrorResource not found/privatemessageHandle missing data
NetworkErrorConnection issuesoriginalErrorRetry logic
try {
  const profile = await api.getProfile('username');
} catch (error) {
  if (error instanceof RateLimitError) {
    console.log(`Retry after: ${error.retryAfter}`);
  } else if (error instanceof NotFoundError) {
    console.log('Profile not found or private');
  }
}

Helper Constants

LOCATIONS

LOCATIONS.US.NEW_YORK        // 105080838 (number)
LOCATIONS.US.SAN_FRANCISCO   // 102277331 (number)
LOCATIONS.US.LOS_ANGELES     // 102448103 (number)
// ... more cities available

COMPANY_SIZES

COMPANY_SIZES.SELF_EMPLOYED  // 'A' (Self-employed)
COMPANY_SIZES.TINY          // 'B' (1-10 employees)
COMPANY_SIZES.SMALL         // 'C' (11-50 employees)
COMPANY_SIZES.MEDIUM        // 'D' (51-200 employees)
COMPANY_SIZES.LARGE         // 'E' (201-500 employees)
COMPANY_SIZES.XLARGE        // 'F' (501-1000 employees)
COMPANY_SIZES.ENTERPRISE    // 'G' (1001-5000 employees)
COMPANY_SIZES.MASSIVE       // 'H' (5001-10000 employees)
COMPANY_SIZES.MEGA          // 'I' (10000+ employees)

INDUSTRIES

INDUSTRIES.TECHNOLOGY         // 96
INDUSTRIES.FINANCIAL_SERVICES // 43
INDUSTRIES.HEALTHCARE         // 14
INDUSTRIES.RETAIL             // 27
// ... more industries available

Troubleshooting

Common Issues & Solutions

ProblemCauseSolution
"Invalid username"Username format incorrectUse LinkedIn username (from URL) not display name
"Rate limit exceeded"Too many requestsImplement delays, use caching, handle RateLimitError
"Profile not found"Private profile or invalid usernameHandle NotFoundError gracefully
Empty search resultsOverly specific criteriaBroaden search parameters
Profile search returns 0 itemsPrivate profiles in result setEnable auto-retry (default) or use debug mode
Slow performanceNot using cachingEnable caching (default) or clear periodically
Memory issuesLarge dataset processingProcess in batches, clear cache regularly

Best Practices

PracticeWhyExample
Use helper constantsAvoid magic stringsgeo: [LOCATIONS.US.NYC] not geo: ['105080838']
Handle errors specificallyBetter error recoveryCheck for RateLimitError, NotFoundError
Use entity methodsSafe data accessprofile.getFullName() not profile.data.firstName
Implement delaysAvoid rate limitsawait new Promise(r => setTimeout(r, 1000))
Load full data smartlyPerformance optimizationSearch first, then load full data only when needed

Parameter Validation

// Validate before making requests
const validation = api.validateParameters('search_people', {
  keywords: 'engineer'
});

if (!validation.valid) {
  console.log('Missing:', validation.missingRequired);
  console.log('Extra:', validation.extraParams);
}

Profile Search & Private Profiles

LinkedIn profile searches may show high total counts but return 0 items due to private profiles. The package automatically handles this:

// Automatic retry (default behavior)
const results = await api.searchProfiles({ keywords: 'engineer' });
// Will try different start positions automatically

// Debug what's happening
api.setDebugMode(true);
const debugResults = await api.searchProfiles({ keywords: 'ceo' });
// Logs: "Profile search attempt 1, start=0: itemsCount=0"
//       "Profile search attempt 2, start=10: itemsCount=2" โœ…

// Manual control
const exactResults = await api.searchProfiles({
  keywords: 'manager',
  autoRetryForPrivateProfiles: false,  // Get exact page
  start: '20'
});

Configuration

The API client supports several configuration options:

const api = new LinkedInAPI('your-key');

// Disable caching
api.enableCache = false;

// Adjust cache timeout (default: 5 minutes)
api.cacheTimeout = 10 * 60 * 1000; // 10 minutes

// Clear cache
api.clearCache();

// Enable debug mode (helpful for troubleshooting)
api.setDebugMode(true);

Rate Limiting

The API includes rate limit information in responses. Handle rate limits gracefully:

try {
  const profile = await api.getProfile('username');
} catch (error) {
  if (error instanceof RateLimitError) {
    console.log(`Rate limited until: ${error.retryAfter}`);
    // Implement retry logic
  }
}

Additional Resources

Use Cases

ScenarioMethods NeededPattern
RecruitingsearchProfiles(), getProfile()Search โ†’ Filter โ†’ Load Full Data
Lead GenerationsearchCompanies(), getCompany()Search by Industry โ†’ Get Details
Market ResearchsearchCompanies(), searchProfiles()Industry Analysis + Employee Insights
Content AnalysissearchPosts(), getPost()Keyword Search โ†’ Engagement Analysis
Competitive IntelligencegetCompany(), searchProfiles()Company Data + Employee Profiles

Contributing

See API_IMPLEMENTATION_GUIDE.md for implementation details and patterns.

License

MIT

Keywords

linkedin

FAQs

Package last updated on 26 Jun 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

About

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.

  • Terms
  • Privacy
  • Security

Made with โšก๏ธ by Socket Inc

U.S. Patent No. 12,346,443 & 12,314,394. Other pending.