The only way you can automate Facebook posts now

I know many of you have moved off of Facebook, but some of us are still addicted to getting Likes for our stupid status updates. I post to Twitter, but Facebook is how I reach that more focused group of people I know called “friends.” The problem is I post to Twitter more than Facebook, and I wouldn’t want those Facebook friends to miss out on all those cool random thoughts I have. Luckily, Twitter has a built-in feature to automatically post Tweets to Facebook via API. This is 2018, after all.

Except Facebook just changed their policy and turned off their API allowing third-party apps to post on our behalf. One day my precious Tweets stopped making it to Facebook and then sometime later Twitter’s docs informed me why. Facebook says third-parties can instead use a popup share dialog for a more “consistent” user experience. Whatever. Of course, this basically breaks any tool that automates posting.

Obviously I’m not going to let this stop me from automating posts. This is 2018! We’ve worked hard to make the world as programmable as it is. I want to enjoy it and automate shit.

So here is a quick tool that lets you post to Facebook via command line. It’s a start, okay? You’ll need Node.js installed and then one library called Puppeteer. This is a high-level wrapper around the Chrome DevTools API, which is amazing and under appreciated. Install it globally with yarn or NPM or whatever:

$ npm install -g puppeteer

Alright, now you can use this script. Which I’m not even going to publish on NPM because it’s like 30 lines. Paste this into a file like fbpost and chmod +x it.

#!/usr/bin/env node
// Usage:
// Login manually, saving your authenticated session in "data":
// $ ./fbpost --login
//
// Now you can post whatever you want via argument:
// $ ./fbpost "Hello world, this is a post!"
//
(async() => {
const puppeteer = require('puppeteer');
const arg = process.argv[2];
const browser = await puppeteer.launch({
headless: (arg !== "--login"),
userDataDir: "data"
});
const page = (await browser.pages())[0];
 await page.goto('https://www.facebook.com');
 if (arg === "--login") {
// wait for homepage to load after a manual login
await page.waitFor('div[aria-label="Create a post"]', {"timeout": 180000});
 } else {
// use keyboard shortcut to open and focus on create new post
await page.keyboard.press('KeyP');
   // wait for emoji icon as proxy for "loaded and post ready"
await page.waitFor('div[aria-label="Create a post"] a[aria-label="Insert an emoji"]')
   // keyboard shortcut put focus in place so we can just type
await page.keyboard.type(arg);
   // click submit
await page.click('div[aria-label="Create a post"] button[type=submit]');
   // can’t find reliable way to detect that it posted successfully,
// but if we close too soon it won’t finish the post request
await new Promise(res => setTimeout(res, 2000));
}
 await browser.close();
})();

Instead of automating authentication, I just let you login via the browser and it’ll keep the Chrome session cookie in the directory data wherever you run this. Feel free to modify this script or do whatever with it. This is currently the only way to programmatically post to Facebook.