BROKE → BUILT EST. 2026 · BUILDING IN PUBLIC · $0 → $4.99
Guides Jul 2, 2026

How to Post to LinkedIn from a Script: the 15-Minute OAuth Walkthrough (2026)

Post to LinkedIn from your own code, no SDK or paid tool: create the app, grab the two self-serve products, run the OAuth dance, and hold a 2-month token.

BROKE → BUILT · GUIDE How to Post to LinkedInfrom a Script: the15-Minute OAuth broke2builtai.com
Short answer

To post to LinkedIn from a script: create an app at linkedin.com/developers/apps (verified against a company page you control — verification is instant for your own page), request the 'Share on LinkedIn' and 'Sign In with LinkedIn using OpenID Connect' products (both instant self-serve grants), and add any https redirect URL on a domain you control — it can even 404, because you only need to copy the ?code= parameter off the redirected URL. Open the /oauth/v2/authorization consent URL with scope openid profile email w_member_social, exchange the code at /oauth/v2/accessToken for an access token that lasts 2 months (5,184,000 seconds), get your member id from GET /v2/userinfo, and POST to https://api.linkedin.com/rest/posts with author urn:li:person:<sub>.

Or skip the work: Meta-Prompt + System Prompt Architect does it in seconds →

Every scheduled-posting tool for LinkedIn wants a subscription for what is, underneath, four HTTP requests. I assumed the DIY route was gated behind a partner-program application and weeks of waiting — that’s the reputation. Then I actually did it today, and the whole thing — app creation to a verified working token — took about fifteen minutes, because the two products a personal posting script needs are instant self-serve checkboxes. Here’s the exact walkthrough, including the one place LinkedIn tried to trip me.

Step 1: Create the app (you need a company page)

Go to linkedin.com/developers/apps and create an app. The one real prerequisite: LinkedIn requires a company page to verify the app against. If the page is yours, this is a non-event — you approve the verification request as the page admin and it’s verified instantly.

Don’t let the company-page requirement confuse you about what you’re building: the app is verified against the page, but with the scopes below you’ll be posting as yourself, to your own member feed.

Step 2: Request the two instant products

On the app’s Products tab, request:

  • Share on LinkedIn — this is what grants the w_member_social scope, the permission to create posts as a member.
  • Sign In with LinkedIn using OpenID Connect — this grants openid profile email, which you need to fetch your own member id.

Both are instant self-serve grants: tick the checkbox, accept the LinkedIn API Terms, done. No review queue, no application essay.

One boundary I hit while poking around: the Community Management API — the product that lets you post as an organization/page rather than as yourself — cannot share an app with other products. It demands its own dedicated app. So if page-posting is in your future, plan on a second app; don’t try to bolt it onto this one.

Step 3: Add a redirect URL (it can literally 404)

On the Auth tab, add an authorized redirect URL. Here’s the part that saves you from standing up a server: any https URL on a domain you control works — even one that returns a 404.

Why: LinkedIn’s OAuth flow ends by redirecting your browser to that URL with ?code=... appended. For a one-time personal-token setup, you don’t need the page to do anything — you just need to read the code parameter out of the address bar after the redirect lands. A dead path on a domain you own is a perfectly valid OAuth redirect target for this purpose.

While you’re on the Auth tab, note your Client ID and Client Secret — and keep the secret out of your repo. Same rule as giving credentials to a scheduled cloud agent: secrets live in environment variables or server-side stores, never in git.

Build this URL (one line) and open it in a browser where you’re logged in to LinkedIn:

https://www.linkedin.com/oauth/v2/authorization
  ?response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=YOUR_REDIRECT_URL
  &scope=openid%20profile%20email%20w_member_social
  &state=SOME_RANDOM_STRING

Approve the consent screen, and LinkedIn bounces you to your redirect URL with ?code=... in the query string. Copy that code — it’s single-use and short-lived, so move straight to the exchange.

The gotcha that got me: LinkedIn may interrupt the consent flow with a security checkpoint asking you to verify your email if the login looks unusual to it. It’s not a bug in your setup — complete the verification and the flow resumes.

Step 5: Exchange the code for a token

Form-encoded POST:

curl -X POST https://www.linkedin.com/oauth/v2/accessToken \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d grant_type=authorization_code \
  -d code=THE_CODE_FROM_THE_REDIRECT \
  -d redirect_uri=YOUR_REDIRECT_URL \
  -d client_id=YOUR_CLIENT_ID \
  -d client_secret=YOUR_CLIENT_SECRET

The response gives you access_token, expires_in: 5184000, an id_token, and the granted scope. That expires_in is the quiet headline: 5,184,000 seconds is two months. For a personal script, that means re-doing this dance six times a year, not building refresh-token plumbing on day one.

Step 6: Verify the token and get your member id

curl https://api.linkedin.com/v2/userinfo \
  -H "Authorization: Bearer <your-access-token>"

This returns your name plus a sub field — your member id. Your author URN for posting is urn:li:person:<sub>. If this call returns your own name, the OAuth leg is done and verified.

Step 7: The post call (per LinkedIn’s docs)

Honesty checkpoint: everything above this line I ran today and watched succeed, through the userinfo verification. The post call itself I’m giving you as documented by LinkedIn — I validated the token and URN, not an actual published post yet.

Per the docs, posting is:

curl -X POST https://api.linkedin.com/rest/posts \
  -H "Authorization: Bearer <your-access-token>" \
  -H "X-Restli-Protocol-Version: 2.0.0" \
  -H "LinkedIn-Version: YYYYMM" \
  -H "Content-Type: application/json" \
  -d '{
    "author": "urn:li:person:YOUR_SUB",
    "commentary": "Posted from a script.",
    "visibility": "PUBLIC",
    "distribution": { "feedDistribution": "MAIN_FEED" },
    "lifecycleState": "PUBLISHED"
  }'

Two headers people miss: X-Restli-Protocol-Version: 2.0.0 is required, and LinkedIn-Version must be a valid YYYYMM API version string — check LinkedIn’s versioning docs for the current active version and substitute it for the placeholder above.

Where this goes next

A two-month token plus a four-request flow is exactly the shape of thing you hand to an agent. Mine drafts in a cheap lane — I run bulk generation on the z.ai GLM Coding Plan (that’s a referral link, it helps fund our compute, and the plan costs the same with or without it; setup in how to set up Claude Code with the GLM API) — and the posting step is just this walkthrough’s step 7 wearing a cron. If you want the whole loop hands-off, the same pattern as scheduling Claude Code to run daily in the cloud applies: keep the LinkedIn token server-side, let the scheduled job call a narrow relay. And if the script needs richer context than “write a post” — your voice, your topics, your rules — that’s a job for a proper instruction stack, the kind you build once with something like an MCP server feeding your agent real data and a prompt written like it has to survive unattended. Meta-Prompt Architect is my tool for exactly that last part: turning “post good stuff to LinkedIn” into instructions precise enough that the 2-month token is the only thing you ever have to touch.

Frequently asked

Do I need a company page to get LinkedIn API access?

Yes — creating an app at linkedin.com/developers/apps requires a LinkedIn company page to verify against. If it's your own page, verification is instant: you approve the request as the page admin and the app is verified on the spot. This is just the app's identity anchor; with the member-posting scopes you'll still be posting as yourself, not as the page.

How long does a LinkedIn access token last?

Two months — the token exchange returns expires_in: 5184000, which is 5,184,000 seconds. That's long enough that for a personal posting script you can treat re-auth as a bi-monthly chore rather than building refresh machinery on day one. Mark the expiry date somewhere you'll actually see it.

Does the OAuth redirect URL need to be a real working endpoint?

No. Any https URL on a domain you control works, even one that returns a 404 — LinkedIn redirects the browser there with ?code=... appended, and all you need is to read that code out of the address bar. You only need a real endpoint if you want the exchange automated end-to-end instead of a one-time copy-paste.

Can I post to a company page with the same app?

Not with this setup. Posting as an organization needs the Community Management API, and LinkedIn requires that product to live on its own dedicated app — it cannot share an app with other products like Share on LinkedIn. Member posting (as yourself) and page posting are two separate apps with separate access processes.

Why is LinkedIn asking me to verify my email during the OAuth consent screen?

LinkedIn can throw a security checkpoint mid-consent — an email verification step — if the login looks unusual to it (new device, automation-adjacent browser, unfamiliar pattern). It's not an error in your OAuth setup. Complete the email verification and the consent flow continues normally.

Some links may be referral links, always marked. Full disclosure →