LinkedInDumper: a one file script that lists a company's employees
Python 3 script to dump/scrape/extract company employees from LinkedIn API
At a glance
- What is it?
- LinkedInDumper is a Python 3 script that talks to the unofficial LinkedIn Voyager API using your own session cookie and returns the first name, last name, job title, location and profile link of a company's employees, optionally generating email addresses from a format string. It runs from a Docker image, from a checkout, or as a script pasted into the browser console.
- Who is it for?
- Adopt LinkedInDumper if you are doing open source intelligence work on a company's public employee footprint and you already have a LinkedIn account and a legitimate reason to look at it, since the script is small enough to read in one sitting and gives you a CSV in a single command.
- Can I use it commercially?
- Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
- Is it still maintained?
- Yes. The repository last received commits 63 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the script returns about each employee
The output is a small, well defined record set: firstname, lastname, position, which the README glosses as the title, location, and a link to the user's profile. Nothing else is collected, and there is no enrichment, no company metadata and no account data. The tool is a directory builder, not an intelligence platform.
The efficiency claim is specific and worth repeating because it tells you how the script works. Only two API calls are required to retrieve all employees if the company does not have more than 10 employees. Otherwise the script has to paginate through the API results. So the design is a single request for the company page, followed by a walk of the paginated employee list, and the cost of a run scales with the size of the company rather than with anything the script does per person.
Two output formats are supported on the command line, --output-json and --output-csv, and the script returns employee data as semi-colon separated values, which the README describes as like CSV. The browser console variant prints the results in the dev console and downloads them as CSV.
The second field of the record set is the one that turns the tool from a curiosity into a targeting aid, which is the email format option, and that is covered separately below.
Your li_at cookie is the entire authentication model
LinkedInDumper talks with the unofficial LinkedIn Voyager API, which requires authentication, so you must have a valid LinkedIn user account. The README is straightforward about how that is supplied: the script expects a cookie value provided by you, and because it is a cookie rather than a password, even accounts protected by two factor authentication are supported.
Getting the cookie is a two step manual process. You sign into www.linkedin.com and retrieve your li_at session cookie value, for example through the browser developer tools. You then specify the value either persistently in the python script's variable li_at, or temporarily at runtime through the --cookie flag.
The persistent option is the one to think about, because it means a live session credential sitting in a source file. The runtime flag keeps it out of the file but puts it in your shell history and, if you wrap the tool in a script, in that script. The README does not discuss either risk, and it does not describe any handling of the cookie beyond passing it through.
The second input is the company URL. You search for the target company on Google Search or directly on LinkedIn, and the URL has the form https://www.linkedin.com/company/apple.
The consequence of this design is worth stating plainly. The script inherits LinkedIn's view of what a logged in user can see, so a company that exposes its employee list to members will yield a long list, and one that restricts it will yield less. The output is bounded by what your own account can already reach.
Three ways to run it, and the console variant needs no install
The Docker route is the shortest. The image is published on Docker Hub as l4rm4nd/linkedindumper, and the run is a single command:
docker run --rm l4rm4nd/linkedindumper:latest --url 'https://www.linkedin.com/company/apple' --cookie '<cookie>' --email-format '{0}.{1}@apple.de'The native route is two commands from a checkout:
# install dependencies
pip install -r requirements.txt
python3 linkedindumper.py --url 'https://www.linkedin.com/company/apple' --cookie '<cookie>' --email-format '{0}.{1}@apple.de'The third route needs nothing installed at all, and it is the most interesting design decision in the project. You open LinkedIn and log in, open the company site with the /company/xxyy path, open the developer console with CTRL+SHIFT+i, paste the contents of console.js and press enter, then define the email format and provide the email domain in JavaScript popups and confirm to start. The results are printed in the dev console and downloaded as CSV.
The reason this works is that the browser is already authenticated and already on the right origin, so the script runs with the session you already have and skips the cookie handling entirely. The README adds a tip that you can prepend javascript: to the content and save it as a browser bookmarklet, which turns the whole tool into a single click on a bookmark.
The repository has both entry points side by side, linkedindumper.py and console.js, and the Dockerfile only copies the Python script, so the browser variant is for people who never clone the repository at all.
The flags that decide how much you collect
The command line interface is where the tool's real behaviour is decided, and several flags change the volume and the sensitivity of what is gathered.
--include-private-profiles shows private accounts too. --include-contact-infos goes further: it queries each employee individually and retrieves their contact infos, which turns a single directory request into one request per person and is the flag most likely to trip rate limits. --jitter adds a random jitter to HTTP requests, and the README states plainly that its purpose is to bypass rate limiting. That flag is the honest signal that the script is not operating within the normal request envelope of the site it queries.
The --email-format option is the one that changes the nature of the output. It takes a Python string format and auto generates email addresses from the retrieved first and last name. The README gives five examples, from {0}.{1}@example.com producing [email protected], through {0[0]}.{1}@example.com producing [email protected], {1}@example.com producing [email protected], {0}@example.com producing [email protected], and {0[0]}{1[0]}@example.com producing [email protected].
That is a pattern guesser, not a verification. The generated address is a plausible string derived from a name and a domain, and it is worth being clear that nothing in the tool confirms that the mailbox exists.
The remaining flags are cosmetic or structural: --quiet, and the two output file options.
The container, the dependencies and a manifest with one field
The Dockerfile is short and gives away the design constraints. It builds FROM python:3.12.4-alpine, labels itself with a maintainer, copies requirements.txt and linkedindumper.py into /app, installs the requirements with pip3, sets the working directory to /app, and runs as USER nobody. The entrypoint is the script itself and the default command is python linkedindumper.py --help, so a bare docker run prints usage rather than starting a server.
The runtime dependencies are two:
requests==2.33.1
Unidecode==1.4.0Unidecode is the interesting one, because it explains how names that are not plain ASCII get turned into email local parts. A name like a Chinese or Cyrillic name has no obvious ASCII form, and transliterating it produces exactly the kind of string an email format like {0[0]}.{1}@example.com can be built from. The choice is a practical one, and it also means the generated local part is a guess about transliteration convention, not a fact about the person's address.
There is also a package.json at the root of the repository that contains a single field:
{
"version": "0.3.7"
}That is a version marker rather than a package manifest, and it suggests the version is read from it at runtime or at build time so that the Docker image tag and the script agree. The repository is otherwise small: .github, CHANGELOG.md, Dockerfile, README.md, console.js, linkedindumper.py, package.json and requirements.txt.
Maintenance, the missing licence and the questions left open
The project is alive but small in its release history. The recent versions are v0.3.7 from 2026-04-18, v0.3.6 from 2025-06-13 and v0.3.5 from 2025-06-03, and the last push to the repository was on 2026-08-21, so the repository is not archived and is being worked on.
The licence is the notable gap. No licence file appears in the repository, and the README does not state one either. For a script whose normal use involves handling other people's names, job titles and email addresses, that is a question worth asking before you deploy it anywhere, and it is also a question your legal team will ask.
Several other things the README does not address are worth naming, because a reader will otherwise assume they are covered. It does not discuss LinkedIn's terms of service or the legal basis for collecting and storing employee contact data, which in most jurisdictions is a real obligation rather than a formality. It does not say how long a run takes, how many requests a paginated company costs, or what rate limit applies. It does not document the format of the CSV beyond saying the values are semi-colon separated, so parsing it is left to you. And it does not say what happens when the cookie expires mid-run, which is a normal event for a session cookie.
The project is advertised as an OSINT tool, and the tooling supports that framing, with a band of flags for including private accounts and pulling per person contact information. The honest assessment is that the script is competent at what it does and modest in scope, and the decisions about whether and how to run it are yours rather than the tool's.
Editorial conclusion
Adopt LinkedInDumper if you are doing open source intelligence work on a company's public employee footprint and you already have a LinkedIn account and a legitimate reason to look at it, since the script is small enough to read in one sitting and gives you a CSV in a single command. Do not adopt it for bulk harvesting, for a marketing list, or anywhere the handling of personal data is not covered by your legal basis, and do not point it at private profiles or the contact info mode without a reason to. Verify first that your own account is permitted to see the data you are about to collect, that the request rate you generate stays inside what LinkedIn allows, since the jitter flag exists precisely because the tool otherwise hits rate limits, and that the licence situation is acceptable, because the repository does not state one.
Frequently asked questions
What does LinkedInDumper extract from LinkedIn?
It returns the first name, last name, position, location and profile link of a company's employees. Only two API calls are needed if the company has no more than 10 employees, otherwise the script paginates through the API results.
How do I give LinkedInDumper my credentials?
It talks with the unofficial LinkedIn Voyager API and expects a cookie value you provide. You retrieve your li_at session cookie from www.linkedin.com with the browser developer tools and either set the li_at variable in the script or pass the value at runtime with the --cookie flag. Because it is a cookie, accounts protected by two factor authentication are supported.
How does the --email-format flag work?
It takes a Python string format and generates email addresses from the retrieved first and last name, for example {0}.{1}@example.com producing [email protected] and {0[0]}.{1}@example.com producing [email protected]. The address is derived from the name, not confirmed to exist.
Can I run LinkedInDumper without installing anything?
Yes. There is a browser console variant: log into LinkedIn, open the company page with the /company/xxyy path, open the developer console with CTRL+SHIFT+i, paste the contents of console.js and press enter, then define the email format and confirm. The README also notes you can prepend javascript: and save it as a bookmarklet.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/l4rm4nd-linkedindumper)Was this useful?