Options
All
  • Public
  • Public/Protected
  • All
Menu

Automation API Documentation

Mouse Clicks, Typing, etc...

NEW!

This Automation API was released in Aug 2019. While it is highly usable, certain things may change slightly over the next few months. We will do our best to ensure backwards compatibility, and all modifications will be listed here:

  • 2019-08-01 Initial release. Bug fixes, no breaking changes.
  • 2019-07-25 Preview release.

Click here to go back to the Standard JSON API Docs

FeedBack, Bugs, or Questions

This API is under active development. Please email Support@PhantomJsCloud.com and we will reply back ASAP, hopefully with a solution to your problem.

Why use it

This api allows unparalleled control over your browser request. Using this Automation API you will be able to do the following things easily:

  • USER INPUT: Control the Keyboard, Mouse, or Touchscreen directly, as a human would.
  • MULTI-RENDERS: Render multiple screenshots or PDF's of the page, at times you decide.
  • CUSTOM LOGIC: A secure sandbox allows custom code (ES2018 javascript) execution inside your API call. This enables dynamic query/manipulation of the page. Full control over the browser.
  • PUPPETEER SCRIPTS: This API implements about 80% of the Puppeteer API, allowing for Puppeteer script compatibility. Current limitations are:
    • Limited to a single page object. You can not create more page objects. This limitation will be lifted in future versions.
    • JSHandle and ElementHandle are not implemented, so these are not returned from function calls. This limitation will be lifted in future versions.
    • Page.on() events are limited to callbacks. No callback sub-function calls (like request.abort()) are currently implemented. This limitation will be lifted in future versions.

Prerequisites

  • Basic Javascript knowledge is recommended. It's best to be familiar with modern Javascript features. It's extremely important to understand the await keyword.
  • DOM Selectors: The easiest way to manipulate the page is to query it using CSS Selectors. Please familiarize yourself with them. An easy way to play with them is:
    • Open Chrome
    • Navigate to a target page (goto http://www.example.com)
    • Open DevTools (Press F12)
    • Open Console (Press Esc)
    • Experiment with Selectors (Type $("h1"); )
  • Use our POST API: While it's possible to call the Automation API via GET it is extremely cumbersome due to the need to urlEncode all non-alphanumeric characters. You really should should construct a JSON object and submit that to our API via the POST body.

Usage

The new overseerScript based API

The main PhantomJsCloud API is used by adding properties to your request's JSON (A Declarative API). This new Automation API is driven by a procedural "overseer" script. This script is executed in a special sandbox that has access to the API documented by this page.

To use this new Automation API, embed your script into the new pageRequest.overseerScript property of the Main Declarative API's REQUEST-JSON

Here is an example of what your REQUEST-JSON would look like:

//a IPageRequest you can submit to the PhantomJsCloud POST API.
{
    //navigate to our automation test page
    url:"http:/PhantomJsCloud.com/examples/corpus/automation.html",
    //outputs a jpeg.  Note the value of the Label in the screenshot
    renderType:"jpeg",
    //request will pause until the DOMReady event, then click the button which changes the label
    overseerScript:'await page.waitForNavigation({waitUntil:"domcontentloaded"});  page.click("input#btn_id_1");',
}

You can try the above example by clicking here.

The new automation renderType

The new overseerScript offers full control over what page(s) are loaded, what to do on the page, and what results are stored.

To go with this flexibility, we added a new renderType:"automation". This will output a JSON containing only the results associated with your overseerScript.

If you do not choose to use the new "automation" renderType, your automation results are still available if you choose outputAsJson:true as described here. Automation results will be found under userResponse.pageResponses.automation.

Here is an example showing some of the capabilities of the new "automation" renderType:

//a IPageRequest you can submit to the PhantomJsCloud POST API.
{
    //navigate to our automation test page
    url:"http:/PhantomJsCloud.com/examples/corpus/automation.html",
    //outputs automation results
    renderType:"automation",
    //request will pause until the DOMReady event, log the value of the label, click the button which changes the label, then log the label value again.
    //then values are stored for the other automation JSON outputs:  rendering, storage, and errorLogs.
    overseerScript:'await page.waitForNavigation({waitUntil:"domcontentloaded"}); \
    await page.meta.log(await page.content({selector:"label#lbl_id_1",type:"plainText"})); \
    await page.click("input#btn_id_1"); \
    await page.meta.log(await page.content({selector:"label#lbl_id_1",type:"plainText"})); \
    //VERY IMPORTANT: comments need a newline character at the end, otherwise the following lines do not get executed.  \n \
    page.render.content(); \
    page.meta.store.set("key1",{some:"json"});  \
    page.meta.logError("test error",{no:1});',
}

Examples

Multiple Page Renders

This example shows how to render both a screenshot and page HTML in a single request. You can try this example by clicking here.

// JSON you can submit to the PhantomJsCloud POST API.
{
    // navigate to example.com
    url:"http://www.example.com",
    // outputs JSON containing only automation results
    renderType:"automation",
    // request will pause until the page LOAD event, then render HTML and a JPEG.   
    overseerScript:'await page.waitForNavigation();  \n page.render.content();  \n await page.render.screenshot();',
    // please note that the above overseerScript is a single string containing javascript.
}

Please note the use of await in front of page.render.screenshot(). This causes the overseerScript to pause until the screenshot is taken.

Type some text, wait 2 seconds, then screenshot

As the above example, this and all overseerScript examples follow a similar workflow, quite easy once you get used to it.

///a IPageRequest you can submit to the PhantomJsCloud POST API.
{
    //no url is sent.  instead, the overseerScript decides what URL and navigates to it.
    //url:"" 
    //after the overseerScript finishes executing, a JPEG will be rendered
    renderType:"jpeg",
    //request will pause until the DOMReady event, then render HTML and a JPEG.   
    overseerScript:' \n\
    await page.goto("http:/PhantomJsCloud.com/examples/corpus/automation.html");  //nav to url, plus wait for it to complete \n\
    await page.click("input[name=\'txt_1\']");  //click on the input box and wait till finished.  \n\
    await page.keyboard.press("Backspace",{times:5}); //delete 5 characters and wait till finished. \n\
    await page.keyboard.type("TYPED!",{delay:10});  //type some text and wait till finish  \n\
    await page.waitForDelay(2000); //wait 2 seconds  \n\
    ',
    //please note that in the above overseerScript lines we add linebreak characters and then a "\" character before a linebreak. 
    //If this is difficult to understand, just don't use linebreaks, and don't use comments in your script and you should be fine.
}

Inject external script that modifies the page

This example injects a custom script and then instructs it to highlight the word "Example". Please take note that to execute javascript in the target page, we use the page.evaluate() function.
You can try this example by clicking here.

{
    "renderType": "jpeg",
    "overseerScript":'await page.goto("http://phantomjscloud.com/examples/corpus/example.com.html"); await page.addScriptTag({url:"http://PhantomJsCloud.com/examples/scripts/hilitor.js"}); await page.evaluate(()=>{let _hilitor=new Hilitor(); _hilitor.apply("Example");});',
}

Login then take a screenshot

Here are three ways to login and take a screenshot.

(For an example of logging into LinkedIn, check the Advanced Scenario Samples)

PLEASE NOTE: In this first example, when clicking the Login button we don't await, instead immediately move to the next line which waits for a page navigation.

///a IPageRequest you can submit to the PhantomJsCloud POST API.
{
    //Normal API navigates to this target page
    url:"http://PhantomJsCloud.com/examples/corpus/automation.html",
    //after the overseerScript finishes executing, a JPEG will be rendered
    renderType:"jpeg",
    //will wait until the text input html element is available, then logs in, waiting for the following page to domReady before finishing.
    overseerScript:' await page.waitForSelector("input[name=id]");  \
    await page.type("input[name=id]","user",{delay:100}); \
    await page.type("input[name=pass]","pass",{delay:100}); \
    page.click("input[type=button][value=Login]"); \
    await page.waitForNavigation();  ',
    //please note that in the above overseerScript lines we add linebreak characters and then a "\" character before a linebreak. 
    //If this is difficult to understand, just don't use linebreaks, and don't use comments in your script and you should be fine.
}

Here's the same workflow as the above example but doing everything via the overseerScript (output is JSON)

///a IPageRequest you can submit to the PhantomJsCloud POST API.
{
    //render a json of just the overseerScript output
    renderType:"automation",
    //will load the url, wait until the text input html element is available, then logs in, waiting for the following page to domReady before taking a screenshot.
    overseerScript:' await page.goto("http://PhantomJsCloud.com/examples/corpus/automation.html"); \
    await page.waitForSelector("input[name=id]");  \
    await page.type("input[name=id]","user",{delay:100}); \
    await page.type("input[name=pass]","pass",{delay:100}); \
    page.click("input[type=button][value=Login]"); \
    await page.waitForNavigation();  \
    await page.render.content(); \
    await page.render.screenshot();',
    //please note that in the above overseerScript lines we add linebreak characters and then a "\" character before a linebreak. 
    //If this is difficult to understand, just don't use linebreaks, and don't use comments in your script and you should be fine.
}

And here we use Promise Chaining along with page.done() instead of pausing via await

///a IPageRequest you can submit to the PhantomJsCloud POST API.
{
    //render a json of just the overseerScript output
    renderType:"automation",
    //will load the url, wait until the text input html element is available, 
    //then logs in, waiting for the following page to domReady before taking a screenshot.
    overseerScript:' page.goto("http://PhantomJsCloud.com/examples/corpus/automation.html"); \
    await page.waitForSelector("input[name=id]");  \
    page.manualWait(); \
    return page.type("input[name=id]","user",{delay:100}) \
    .then(()=>{ return page.type("input[name=pass]","pass",{delay:100});  }) \
    .then(async ()=>{ \
        page.click("input[type=button][value=Login]");   \
        await page.waitForNavigation();   \
        await page.render.content(); \
        await page.render.screenshot(); \
        page.done(); \
    }); ',
}

Render at DOMReady

This example renders a jpeg as soon as the domReady event is triggered, resulting in a more than 2x speedup of the cnn.com website. Rendering at DomReady is much faster but depending on the site may be less accurate. You can try this example by clicking here.

{
    "url":"http://cnn.com",
    "renderType": "jpeg",
    "overseerScript":'await page.waitForNavigation({waitUntil:"domcontentloaded"}); page.done();',
}

More examples

For more examples, check the Advanced Scenario Samples

Where to look next

The best docs to start diving in is the Page documentation.

Troubleshooting

weird overseerScript behavior

  • choose either outputAsJson:true or set your renderType:automation to check for automation errors.
  • make sure that any commented lines in your overseerScript end with a newline character (\n)
  • make sure that you use the await keyword to wait for a command to finish before executing the next line.
  • By default the API call will not render until your overseerScript completes. You can call page.done() to signal your script is done earlier.
  • try using page.meta.log("here") to check how far in your script you execute, and use the log function to output debug state for troubleshooting
  • email your script to **support@PhantomJsCloud.com** and we'll help as soon as possible.

timeout on page waitForNavigation

await page.waitForNavigation(); will wait forever if no page navigation occurs after it is called.

For example, this will stall:

 //navigate to example.com and wait till done
await page.goto("http://www.example.com");
//wait for a navigation to complete
await page.waitForNavigation();  

but this will not stall, because the navigation doesn't occur until after waitForNavigation() is called:

 //start navigating to example.com and continue script execution immediately
page.goto("http://www.example.com");
//wait for a navigation to complete
await page.waitForNavigation();  

blank result

  • make sure you don't include a pageRequest.url property if your overseerScript uses page.goto()
  • make sure you use await in your overseerScript when you need to wait for something to occur.
  • try adding page.manualWait() to control when the page finishes, and make sure you call page.done() when ready.

reading error information

There are a few ways to obtain error details from your API Response

  • HTTP Response StatusCode: a 400+ status code represents an error with your request or the target server. a 500+ status code is an error with the PhantomJsCloud API. See the Basic Troubleshooting section of the doc page for more info.
  • HTTP Response Headers: we try to summarize high-level information in the http response headers, so check here might give a summary of what an issue is.
  • Automation Errors: any errors encountered by the automation script will be under the pageResponse.automation.errors node.
  • Other Errors: other errors encountered wll be under pageResponse.errors though you may need to look under pageResponses.events and/or meta.trace to see error details.

Open Source Notice

  • documentation makes use of portions of the following open source projects
    • Xlib: github.com/Novaleaf/xlib
    • Puppeteer: github.com/GoogleChrome/puppeteer
    • Bluebird: github.com/petkaantonov/bluebird
    • TypeDoc: github.com/TypeStrong/typedoc
    • MDN: developer.mozilla.org/en-US/docs/Web

Index

Type aliases

ConsoleMessageType

ConsoleMessageType: "log" | "debug" | "info" | "error" | "warning" | "dir" | "dirxml" | "table" | "trace" | "clear" | "startGroup" | "startGroupCollapsed" | "endGroup" | "assert" | "profile" | "profileEnd" | "count" | "timeEnd"

HttpMethod

HttpMethod: "GET" | "POST" | "PATCH" | "PUT" | "DELETE" | "OPTIONS"

LayoutDimension

LayoutDimension: string | number

Accepts values labeled with units. If number, treat as pixels.

LoadEvent

LoadEvent: "load" | "domcontentloaded" | "networkidle0" | "networkidle2"

MouseButtons

MouseButtons: "left" | "right" | "middle"

PDFFormat

PDFFormat: "Letter" | "Legal" | "Tabloid" | "Ledger" | "A0" | "A1" | "A2" | "A3" | "A4" | "A5"

ResourceType

ResourceType: "document" | "stylesheet" | "image" | "media" | "font" | "script" | "texttrack" | "xhr" | "fetch" | "eventsource" | "websocket" | "manifest" | "other"

SameSiteSetting

SameSiteSetting: "Strict" | "Lax"