https://w3c.github.io/webdriver/webdriver-spec.html
Run your local firefox installation in marionette mode:
$ firefox --marionette 1508154717660 Marionette INFO Enabled via --marionette 1508154718454 Marionette INFO Listening on port 2828
Run geckodriver WebDriver proxy:
$ ./bin/geckodriver --connect-existing --marionette-port 2828 1508154721745 geckodriver INFO geckodriver 0.19.0 1508154721755 geckodriver INFO Listening on 127.0.0.1:4444
Use curl to control it:
$ curl -s -d '{}' http://localhost:4444/session | jq . { "value": { "sessionId": "f1c4ec02-3edc-4308-a0a8-697edd383b9a", "capabilities": { "acceptInsecureCerts": false, "browserName": "firefox", "browserVersion": "56.0", "moz:accessibilityChecks": false, "moz:headless": false, "moz:processID": 26238, "moz:profile": "/home/cweiske/.mozilla/firefox/u05dh3q4.default", "pageLoadStrategy": "normal", "platformName": "linux", "platformVersion": "4.12.3cw", "rotatable": false, "specificationLevel": 0, "timeouts": { "implicit": 0, "pageLoad": 300000, "script": 30000 } } } } $ session=f1c4ec02-3edc-4308-a0a8-697edd383b9a $ curl -s -d '{"url":"http://example.org"}' http://localhost:4444/session/$session/url | jq . { "value": {} } $ curl -s http://localhost:4444/session/$session/title | jq . { "value": "Example Domain" } $ curl -s http://localhost:4444/session/$session/url | jq . { "value": "http://example.org/" } $ curl -s -d '{"using":"xpath","value":"//h1"}' http://localhost:4444/session/$session/element | jq . { "value": { "element-6066-11e4-a52e-4f735466cecf": "4131ac8d-651c-4903-8b04-a591f4f7456f" } } $ curl -s -d '{"using":"xpath","value":"//doesnotexist"}' http://localhost:4444/session/$session/element | jq . { "value": { "error": "no such element", "message": "Unable to locate element: //doesnotexist", "stacktrace": "stack backtrace:\n 0: 0x4f388c - backtrace::backtrace::trace::h736111741fa0878e\n 1: 0x4f38c2 - backtrace::capture::Backtrace::new::h63b8a5c0787510c9\n 2: 0x442d88 - webdriver::error::WebDriverError::new::hea6d4dbf778b2b24\n 3: 0x44cecc - geckodriver::marionette::MarionetteSession::response::h98d048d51a7ee2ba\n 4: 0x42c729 - <webdriver::server::Dispatcher<T, U>>::run::hba9181b5aacf8f04\n 5: 0x402c59 - std::sys_common::backtrace::__rust_begin_short_backtrace::h19de262639927233\n 6: 0x40c065 - std::panicking::try::do_call::h6c1659fc4d01af51\n 7: 0x5e38ec - panic_unwind::__rust_maybe_catch_panic\n at /checkout/src/libpanic_unwind/lib.rs:98\n 8: 0x420d32 - <F as alloc::boxed::FnBox<A>>::call_box::h953e5f59694972c5\n 9: 0x5dc00b - alloc::boxed::{{impl}}::call_once<(),()>\n at /checkout/src/liballoc/boxed.rs:661\n - std::sys_common::thread::start_thread\n at /checkout/src/libstd/sys_common/thread.rs:21\n - std::sys::imp::thread::{{impl}}::new::thread_start\n at /checkout/src/libstd/sys/unix/thread.rs:84" } }