# Can you access AXIS PTZ controls via Ignition?

**URL:** <https://forum.inductiveautomation.com/t/can-you-access-axis-ptz-controls-via-ignition/85175>\
**Category:** Ignition\
**Tags:** ignition81, perspective\
**Created:** [February 2, 2024, 8:31pm UTC](https://forum.inductiveautomation.com/t/can-you-access-axis-ptz-controls-via-ignition/85175 "2024-02-02T20:31:07Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![Cameron\_Nickle](https://avatars.discourse-cdn.com/v4/letter/c/b3f665/32.png) [@Cameron\_Nickle](https://forum.inductiveautomation.com/u/Cameron_Nickle)\
**Post date:** [February 2, 2024, 8:31pm UTC](https://forum.inductiveautomation.com/t/can-you-access-axis-ptz-controls-via-ignition/85175/1 "2024-02-02T20:31:07Z")

</div>

This is a broad question and I'm not certain if its even possible but I'm genuinely curios if there is a way to make some form of call from a perspective session to control an AXIS Pan-Tilt-Zoom camera.

This is a very loaded question, but if anyone has any ideas of how this may be possible I'm all ears.

Thank you,

Cam

---

<div class="post-metadata">

**Author:** ![bmusson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bmusson/32/87530_2.png) [@bmusson](https://forum.inductiveautomation.com/u/bmusson)\
**Post date:** [February 2, 2024, 8:40pm UTC](https://forum.inductiveautomation.com/t/can-you-access-axis-ptz-controls-via-ignition/85175/2 "2024-02-02T20:40:53Z")

</div>

You have a whole library of APIs you can call with web requests, check out the PTZ section.

> **[VAPIX® Library | Axis Communications](https://www.axis.com/vapix-library/)**
>
> The complete reference library for all VAPIX® APIs | VAPIX® Library | Axis Communications

---

<div class="post-metadata">

**Author:** ![Cameron\_Nickle](https://avatars.discourse-cdn.com/v4/letter/c/b3f665/32.png) [@Cameron\_Nickle](https://forum.inductiveautomation.com/u/Cameron_Nickle)\
**Post date:** [February 2, 2024, 10:48pm UTC](https://forum.inductiveautomation.com/t/can-you-access-axis-ptz-controls-via-ignition/85175/3 "2024-02-02T22:48:29Z")

</div>

This is exceptional! Thank you!

However, I am now facing a different issue that you may also have ran into if you know about these.

This is my very simple function call on a button click event:

```auto
system.net.httpGet("https://10.10.0.3/axis-cgi/com/ptz.cgi?zoom=1000", username = " ***", password = "***")

```

The username and password fields are correct on my end.

This is giving me this error:

```auto
com.inductiveautomation.ignition.common.script.JythonExecException: Traceback (most recent call last): File "", line 2, in runAction IOError: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at org.python.core.Py.fromIOException(Py.java:216)
at org.python.core.Py.IOError(Py.java:183)
at com.inductiveautomation.ignition.common.script.builtin.AbstractNetUtilities.httpGet(AbstractNetUtilities.java:274)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at org.python.core.PyReflectedFunction. __call__ (PyReflectedFunction.java:190)
at com.inductiveautomation.ignition.common.script.ScriptManager$ReflectedInstanceFunction. __call__ (ScriptManager.java:552)
at org.python.core.PyObject. __call__ (PyObject.java:400)
at org.python.pycode._pyx17.runAction$1(:2)
at org.python.pycode._pyx17.call_function()
at org.python.core.PyTableCode.call(PyTableCode.java:173)
at org.python.core.PyBaseCode.call(PyBaseCode.java:306)
at org.python.core.PyFunction.function ___call__ (PyFunction.java:474)
at org.python.core.PyFunction. __call__ (PyFunction.java:469)
at org.python.core.PyFunction. __call__ (PyFunction.java:464)
at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:846)
at com.inductiveautomation.ignition.common.script.ScriptManager.runFunction(ScriptManager.java:828)
at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$TrackingProjectScriptManager.runFunction(ProjectScriptLifecycle.java:832)
at com.inductiveautomation.ignition.common.script.ScriptManager$ScriptFunctionImpl.invoke(ScriptManager.java:1009)
at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle$AutoRecompilingScriptFunction.invoke(ProjectScriptLifecycle.java:897)
at com.inductiveautomation.perspective.gateway.script.ScriptFunctionHelper.invoke(ScriptFunctionHelper.java:158)
at com.inductiveautomation.perspective.gateway.script.ScriptFunctionHelper.invoke(ScriptFunctionHelper.java:97)
at com.inductiveautomation.perspective.gateway.action.ScriptAction.runAction(ScriptAction.java:74)
at com.inductiveautomation.perspective.gateway.action.ActionDecorator.runAction(ActionDecorator.java:18)
at com.inductiveautomation.perspective.gateway.action.SecuredAction.runAction(SecuredAction.java:44)
at com.inductiveautomation.perspective.gateway.model.ActionCollection$ActionSequence$ExecuteActionsTask.lambda$call$0(ActionCollection.java:263)
at com.inductiveautomation.perspective.gateway.api.LoggingContext.mdc(LoggingContext.java:54)
at com.inductiveautomation.perspective.gateway.model.ActionCollection$ActionSequence$ExecuteActionsTask.call(ActionCollection.java:252)
at com.inductiveautomation.perspective.gateway.model.ActionCollection$ActionSequence$ExecuteActionsTask.call(ActionCollection.java:221)
at com.inductiveautomation.perspective.gateway.threading.BlockingTaskQueue$TaskWrapper.run(BlockingTaskQueue.java:154)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at com.inductiveautomation.perspective.gateway.threading.BlockingWork$BlockingWorkRunnable.run(BlockingWork.java:58)
at java.base/java.lang.Thread.run(Unknown Source)
Caused by: org.python.core.PyException: IOError: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
... 38 common frames omitted

```

Its very long and gross but it confuses me because the get request has the identification credentials and it seems to be a security error.

not sure how to proceed but any insights would be helpful while I try and fix this issue.

Thank you,

Cam

---

<div class="post-metadata">

**Author:** ![bmusson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bmusson/32/87530_2.png) [@bmusson](https://forum.inductiveautomation.com/u/bmusson)\
**Post date:** [February 2, 2024, 11:10pm UTC](https://forum.inductiveautomation.com/t/can-you-access-axis-ptz-controls-via-ignition/85175/4 "2024-02-02T23:10:40Z")

</div>

Try the call over HTTP instead of HTTPS. The camera is probably using a self signed certificate.

Also, you should use [system.net.httpClient](https://docs.inductiveautomation.com/display/DOC81/system.net.httpClient) instead of `system.net.httpGet`, my understanding is that `.httpGet` is just leftover for legacy reasons.

---

<div class="post-metadata">

**Author:** ![Cameron\_Nickle](https://avatars.discourse-cdn.com/v4/letter/c/b3f665/32.png) [@Cameron\_Nickle](https://forum.inductiveautomation.com/u/Cameron_Nickle)\
**Post date:** [February 6, 2024, 4:40pm UTC](https://forum.inductiveautomation.com/t/can-you-access-axis-ptz-controls-via-ignition/85175/5 "2024-02-06T16:40:22Z")

</div>

With a little looking it seems that the self signed certificate is not trusted. So I added a bypass for testing purposes to see if I could actually make it work before I went about adding the certificate and what not. (from here: [Unable to POST on a REST API using https - #8 by Ben\_Hunt](https://forum.inductiveautomation.com/t/unable-to-post-on-a-rest-api-using-https/66769/8))

This is currently what I have in a simple button event:

```auto
client = system.net.httpClient(bypass_cert_validation = True)
url = "https://10.10.0.3/axis-cgi/com/ptz.cgi?zoom=1000"
client.post(url)

```

```auto
<Response@1172685220 'https://10.10.0.3/axis-cgi/com/ptz.cgi?zoom=1000' [401]>

```

However, this still does not seem to accept the zoom function to the camera regardless of HTTP or HTTPS. The password and username variables also don't seem to make a difference. 401 is still the return.

The weird thing about this is I did a basic test and just threw the URL into a browser and ran it and it will zoom the camera in but not via the button.

If you have any further suggestions they would be greatly appreciated.

Thank you,

Cam

---

<div class="post-metadata">

**Author:** ![bmusson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bmusson/32/87530_2.png) [@bmusson](https://forum.inductiveautomation.com/u/bmusson)\
**Post date:** [February 6, 2024, 5:40pm UTC](https://forum.inductiveautomation.com/t/can-you-access-axis-ptz-controls-via-ignition/85175/6 "2024-02-06T17:40:03Z")

</div>

You will definitely need to authenticate before you can make the API call.  
IIRC Axis cameras use Digest Auth.

---

<div class="post-metadata">

**Author:** ![Cameron\_Nickle](https://avatars.discourse-cdn.com/v4/letter/c/b3f665/32.png) [@Cameron\_Nickle](https://forum.inductiveautomation.com/u/Cameron_Nickle)\
**Post date:** [February 6, 2024, 9:10pm UTC](https://forum.inductiveautomation.com/t/can-you-access-axis-ptz-controls-via-ignition/85175/7 "2024-02-06T21:10:48Z")

</div>

Have you been able to work with the AXIS cameras through ignition? Because I did some more digging and found this:

> [@How to use digest authentication in httpBinding](https://forum.inductiveautomation.com/t/how-to-use-digest-authentication-in-httpbinding/83786):
>
> I can't understand where I should write down username and password? Everytime I get 401 Unauthorized error as response.

which informed me via the .net function provided by ignition you cannot authenticate with these cameras to perform actions?

I have an idea for a potential work around that involves the 'requests' header in python but cannot seem to add it to the scripting library properly to call it. Would you happen to know how to do that? Or do you have a better way?

Thank you,

Cam

---

<div class="post-metadata">

**Author:** ![bmusson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bmusson/32/87530_2.png) [@bmusson](https://forum.inductiveautomation.com/u/bmusson)\
**Post date:** [February 7, 2024, 12:51am UTC](https://forum.inductiveautomation.com/t/can-you-access-axis-ptz-controls-via-ignition/85175/8 "2024-02-07T00:51:23Z")

</div>

> [@Cameron\_Nickle](#):
>
> Have you been able to work with the AXIS cameras through ignition?

I have, but it’s been a while and I don’t have a code reference or a camera to test with (our office cameras are Axis, but they’re on a VLAN I can’t reach without much effort).

Try looking up resources for accomplishing digest auth with Java’s HTTP client. The examples will need to be adapted for Jython, but the same general approach will apply.

[Relevant SO thread.](https://stackoverflow.com/questions/73264239/digest-authentication-java-net-http-httpclient)

---

<div class="post-metadata">

**Author:** ![Andrii\_Ushchapovskyi](https://avatars.discourse-cdn.com/v4/letter/a/a3d4f5/32.png) [@Andrii\_Ushchapovskyi](https://forum.inductiveautomation.com/u/Andrii_Ushchapovskyi)\
**Post date:** [February 7, 2024, 9:27am UTC](https://forum.inductiveautomation.com/t/can-you-access-axis-ptz-controls-via-ignition/85175/9 "2024-02-07T09:27:51Z")

</div>

Hello,

I am using this script to connect to HIKVision camera with digest authentification

````auto
import urllib2 
p = urllib2.HTTPPasswordMgrWithDefaultRealm()
p.add_password(None, "http://{0}/ISAPI/ContentMgmt/search".format(self.getSibling("TextField_CameraIP").props.text), "{0}".format(self.getSibling("TextField_CameraUser").props.text), "{0}".format(self.getSibling("PasswordField_Camera").props.text))
handler = urllib2.HTTPDigestAuthHandler(p)
opener = urllib2.build_opener(handler)
urllib2.install_opener(opener)
request = urllib2.Request("http://{0}/ISAPI/ContentMgmt/search".format(self.getSibling("TextField_CameraIP").props.text), data='<?xml version="1.0" encoding="utf-8"?><CMSearchDescription><searchID>8EEB2D93-199C-422E-AC4B-2FEAFD8411A5</searchID><trackList><trackID>101</trackID></trackList><timeSpanList><timeSpan><startTime>{0}</startTime><endTime>{1}</endTime></timeSpan></timeSpanList><maxResults>100</maxResults></CMSearchDescription>'.format(start, end))
f = opener.open(request)
tracks = f.read()```
````

---

<div class="post-metadata">

**Author:** ![Cameron\_Nickle](https://avatars.discourse-cdn.com/v4/letter/c/b3f665/32.png) [@Cameron\_Nickle](https://forum.inductiveautomation.com/u/Cameron_Nickle)\
**Post date:** [February 7, 2024, 9:29pm UTC](https://forum.inductiveautomation.com/t/can-you-access-axis-ptz-controls-via-ignition/85175/10 "2024-02-07T21:29:37Z")

</div>

Thank you both!

Cam

---

<div class="post-metadata">

**Author:** ![Cameron\_Nickle](https://avatars.discourse-cdn.com/v4/letter/c/b3f665/32.png) [@Cameron\_Nickle](https://forum.inductiveautomation.com/u/Cameron_Nickle)\
**Post date:** [February 11, 2024, 6:32pm UTC](https://forum.inductiveautomation.com/t/can-you-access-axis-ptz-controls-via-ignition/85175/11 "2024-02-11T18:32:07Z")

</div>

Hi Andrii,

I know this thread is technically closed but I was just wondering if you know how to make calls that involve JSON? Because I can get the simple ones to work that move the camera but I cannot get the ones with JSON to work for user management and things like that.

To be more specific something like this:

 ![image](https://us1.discourse-cdn.com/inductiveautomation/original/3X/c/e/cecad879b7ab527d1dee5d12686464390e2d1307.png)

Thank you,

Cam

---

<div class="post-metadata">

**Author:** ![Andrii\_Ushchapovskyi](https://avatars.discourse-cdn.com/v4/letter/a/a3d4f5/32.png) [@Andrii\_Ushchapovskyi](https://forum.inductiveautomation.com/u/Andrii_Ushchapovskyi)\
**Post date:** [February 12, 2024, 7:06am UTC](https://forum.inductiveautomation.com/t/can-you-access-axis-ptz-controls-via-ignition/85175/12 "2024-02-12T07:06:43Z")

</div>

Hi Cam,

I guess you should send POST request with json body.  
Here is an [example](https://stackoverflow.com/questions/3238925/python-urllib-urllib2-post) how to do it with urllib2 library

---

<div class="post-metadata">

**Author:** ![Phillip\_Jackson](https://avatars.discourse-cdn.com/v4/letter/p/f04885/32.png) [@Phillip\_Jackson](https://forum.inductiveautomation.com/u/Phillip_Jackson)\
**Post date:** [March 3, 2025, 4:49pm UTC](https://forum.inductiveautomation.com/t/can-you-access-axis-ptz-controls-via-ignition/85175/13 "2025-03-03T16:49:15Z")

</div>

I was able to get a digest auth handshake to work to issue a command to an Axis camera as detailed in: [How to use digest authentication in httpBinding](https://forum.inductiveautomation.com/t/how-to-use-digest-authentication-in-httpbinding/83786/13)
