Prog blog

How to update DNS record in namecheap using puppeteer

How to update DNS record in namecheap using puppeteer

Yesterday I bought the nolife.cyou domain on namecheap.com to escape the free firebase domain blog-81003.web.app and extend the capabilities of my blog by serving 100% content from IPFS. But as it turned out after the purchase (this is my first purchase on namecheap) I don't have the possibility to access the namecheap API.

namecheap.com blocked API screenshot

But it is not a big problem if you can use a puppeteer. The script written below allows us to automatically update the selected dns record. The record must be already in the DNS records, otherwise the script will not edit it.

const puppeteer = require('puppeteer');
const pixel2 = puppeteer.devices['Pixel 2'];
const args = process.argv.slice(2);

const login = process.env.NC_LOGIN;
const password = process.env.NC_PASSWORD;
const domain = args[0];
const record = args[1];
const value = args[2];

if (!domain) {
  throw new Error('Missing domain argument');
}

if (!record) {
  throw new Error('Missing record argument');
}

if (!value) {
  throw new Error('Missing value argument');
}

(async () => {
  const browser = await puppeteer.launch({
    args: ['--no-sandbox']
  });
  try {
    const page = await browser.newPage();
    await page.emulate(pixel2);
    await page.goto(`https://ap.www.namecheap.com/Domains/DomainControlPanel/${domain}/advancedns`, {
      waitUntil: 'networkidle2'
    });
    await page.waitForSelector('input.nc_username');
    await page.focus('input.nc_username');
    await page.keyboard.type(login);
    await page.waitForSelector('input.nc_password');
    await page.focus('input.nc_password');
    await page.keyboard.type(password);
    await page.click('input[type="submit"]');
    const recordElement = await page.waitForXPath(`//tr[descendant::p[text() = '${record}']]`);
    const editButton = await recordElement.$('a.mobile-edit');
    await editButton.click();
    const valueInput = await page.waitForSelector('.content .row input[placeholder="Value"]');
    await valueInput.focus();
    await valueInput.evaluate(el => el.value = '');
    await page.keyboard.type(value);
    await page.click('.content .actions .btn');
    await page.waitForXPath(`//tr[descendant::p[text() = '${record}'] and descendant::p[text() = '${value}']]`);
  } catch (error) {
    await browser.close();
    throw error;
  }
  await browser.close();
})().catch(error => {
  console.error(error);
  process.exit(1);
});

An example of how to update a _dnslink record for the nolife.cyou domain.

NC_LOGIN=login NC_PASSWORD='password' node index.js nolife.cyou _dnslink dnslink=/ipfs/QmSnZD4dzkz6WebJihL8SurLdPH5mXa5VyYvjBuyKewxQu

If you have no particular reason to update the above code, you can always install the program straight from gist.

npm i gist:ae0b46331bd7407c621d0a2b426cbc5c

An example of how to update a _dnslink record for the nolife.cyou domain.

npx namecheap-update-dns nolife.cyou _dnslink dnslink=/ipfs/QmSnZD4dzkz6WebJihL8SurLdPH5mXa5VyYvjBuyKewxQu

If you have an idea how to improve the code below, please write about it in comments. :)