Skip to content

Instantly share code, notes, and snippets.

@DickyT
Created December 6, 2019 12:30
Show Gist options
  • Save DickyT/f99108bf81963921ce00031fa5545421 to your computer and use it in GitHub Desktop.
Save DickyT/f99108bf81963921ce00031fa5545421 to your computer and use it in GitHub Desktop.
Trigger Find My iPhone Alarm with Puppeteer
const puppeteer = require('puppeteer');
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
const playSoundOnDevice = async (username, password, deviceName) => {
const browser = await puppeteer.launch({
args: [
'--disable-features=site-per-process',
'--user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"'
],
headless: true,
});
const page = await browser.newPage();
await page.goto('https://www.icloud.com/find', {
waitUntil: 'domcontentloaded',
});
await page.waitForSelector('iframe#auth-frame');
const loginFrame = await page.$('iframe#auth-frame');
const loginContent = await loginFrame.contentFrame();
await loginContent.waitForSelector('#account_name_text_field');
const loginInput = await loginContent.$('#account_name_text_field');
loginInput.type(username);
await sleep(1000);
await loginContent.click('#remember-me');
await loginContent.click('#sign-in');
await sleep(1000);
const passwordInput = await loginContent.$('[type=password]');
passwordInput.type(password);
await sleep(1000);
await loginContent.click('#sign-in');
await sleep(1000);
await page.waitForNavigation({
waitUntil: 'networkidle2',
});
console.log('LOGIN OK');
await page.waitForSelector('iframe#find');
const findFrame = await page.$('iframe#find');
const findContent = await findFrame.contentFrame();
await sleep(1000);
await findContent.click('.devices-btn');
await sleep(1000);
const targetDeviceId = await findContent.evaluate((deviceName) => {
const itemList = document.querySelectorAll('div.st-deviceList > div:not(.disabled)');
const target = Array.prototype.find.call(itemList, d => d.querySelector('.device-name').textContent === deviceName);
return target ? target.id : null;
}, deviceName);
if (targetDeviceId) {
await findContent.click(`#${targetDeviceId}`);
await sleep(500);
const targetButtonId = await findContent.evaluate(() => {
const itemList = document.querySelectorAll('.st-playSoundBtn');
const target = Array.prototype.find.call(itemList, d => d.offsetParent !== null);
return target ? target.id : null;
});
console.log('PLAYING SOUND!');
await findContent.click(`#${targetButtonId}`);
await sleep(5000);
} else {
console.log('DEVICE NOT FOUND');
}
await browser.close();
};
module.exports = { playSoundOnDevice };
@DickyT
Copy link
Author

DickyT commented Dec 6, 2019

How to use

const { playSoundOnDevice } = require('./icloud.js');
playSoundOnDevice('timcook@icloud.com', 'Password123', 'Tim Cook\'s iPhone');

Platform

  • Windows 10
  • macOS

ARM is not working, it seems like Chromium 74 is not working well with puppeteer or puppeteer-core, there are some solutions online, but none of them works for my raspberry pi 2.

Other platforms not tested.

Tips

You might want to only host this application at home, because this script CANNOT override MFA. However, if you previously authorized iCloud at home with the same IP address, iCloud would not ask you for MFA code again.

@DickyT
Copy link
Author

DickyT commented Dec 6, 2019

Boring Story

I am waiting for my dream company's decision email, and I could not sleep well, because I will wake up eventually to check my mailbox.

This tool was initially triggered by an email filter, so when a new email comes in, matches my rule, it will make my iPhone sound, so I will not miss important emails.

After making this script, I realized that people might be able to use this to connect their smart home network, such as an IoT button, like when you cannot find your phone, press that button, and the phone will play a sound.

Feedback

Reply below if you have any questions using this script.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment