# Issue with Kepware API Script in Ignition's Project Library (401 Error)

**URL:** <https://forum.inductiveautomation.com/t/issue-with-kepware-api-script-in-ignitions-project-library-401-error/101600>\
**Category:** Automated Testing\
**Created:** [January 30, 2025, 5:59am UTC](https://forum.inductiveautomation.com/t/issue-with-kepware-api-script-in-ignitions-project-library-401-error/101600 "2025-01-30T05:59:44Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![WishahNaseer](https://avatars.discourse-cdn.com/v4/letter/w/f04885/32.png) [@WishahNaseer](https://forum.inductiveautomation.com/u/WishahNaseer)\
**Post date:** [January 30, 2025, 5:59am UTC](https://forum.inductiveautomation.com/t/issue-with-kepware-api-script-in-ignitions-project-library-401-error/101600/1 "2025-01-30T05:59:44Z")

</div>

Hi everyone,

I've written two scripts to automate the creation of channels, devices, tag groups, and tags in Kepware using its API.

1. **Script 1** : Uses API requests via system.net.httpClient().
2. **Script 2** : Uses Kepware's Python libraries (kepconfig).

**Issue**

When I run **Script 1** :  
It works fine in:

- **Local IDE (e.g., PyCharm, VS Code, etc.)**
- **Ignition's Script Console**
- **Directly on an Ignition component (e.g., button script)**

However, when I move it to **Ignition's Project Library** and try executing the function, I get a 401 Unauthorized error.

**What I've Tried**

- Checked authentication details (same credentials work in other cases).
- Used both system.net.httpPost() and system.net.httpClient().post().
- Verified that Kepware is running and accessible.
- Confirmed that Script 2 (using kepconfig) works without issues.

Has anyone encountered this before? Could there be a difference in how Ignition handles authentication for scripts in the Project Library vs. direct execution?

**Scripts Below for Reference:**  
(Script 1 - API requests)

```python

import json
def createChannel(channelName, deviceDriver):
url = "http://127.0.0.1:57412/config/v1/project/channels"
payload = {
"common.ALLTYPES_NAME": channelName,
"servermain.MULTIPLE_TYPES_DEVICE_DRIVER": deviceDriver
}
headers = {
'Authorization': 'Basic Q………….',
'Content-Type': 'application/json'
}
response = system.net.httpClient().post(url, headers=headers, data=json.dumps(payload))
print("Create Channel Response:", response.statusCode)

```

(Similar functions for device, tag group, and tag creation)

(Script 2 - Kepware libraries)

```python
import kepconfig.connection as connection
import kepconfig.connectivity as connectivity
from kepconfig.connectivity import channel, device, tag
server = connection.server(host='127.0.0.1', port=57412, user='Administrator', pw='')
try:
    channel_data = {"common.ALLTYPES_NAME": "ChannelY", "servermain.MULTIPLE_TYPES_DEVICE_DRIVER": "Modbus TCP/IP Ethernet"}
    channel.add_channel(server, channel_data)
except:
    print("Channel exists")

```

(Similar structure for device, tag group, and tag creation)  
Version: _8.1.36_  
Any insights or suggestions would be greatly appreciated! Thanks in advance.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [January 30, 2025, 12:54pm UTC](https://forum.inductiveautomation.com/t/issue-with-kepware-api-script-in-ignitions-project-library-401-error/101600/2 "2025-01-30T12:54:25Z")

</div>

In a project library, all code you expect to use must be in a function, so you can call the function. Indentation matters.

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [January 30, 2025, 1:00pm UTC](https://forum.inductiveautomation.com/t/issue-with-kepware-api-script-in-ignitions-project-library-401-error/101600/3 "2025-01-30T13:00:23Z")

</div>

If this is really just http and not https you should be able to do a Wireshark capture and see what’s different about the requests.

---

<div class="post-metadata">

**Author:** ![WishahNaseer](https://avatars.discourse-cdn.com/v4/letter/w/f04885/32.png) [@WishahNaseer](https://forum.inductiveautomation.com/u/WishahNaseer)\
**Post date:** [February 3, 2025, 5:59am UTC](https://forum.inductiveautomation.com/t/issue-with-kepware-api-script-in-ignitions-project-library-401-error/101600/4 "2025-02-03T05:59:21Z")

</div>

> [@pturmel](#):
>
> n a project library, all code you expect to use must be in a function, so you can call the function. Indentation matters.

Yes, I made sure it is in a function and properly indented.

---

<div class="post-metadata">

**Author:** ![Gaurav.Shitole](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/gaurav.shitole/32/72050_2.png) [@Gaurav.Shitole](https://forum.inductiveautomation.com/u/Gaurav.Shitole)\
**Post date:** [February 3, 2025, 8:43am UTC](https://forum.inductiveautomation.com/t/issue-with-kepware-api-script-in-ignitions-project-library-401-error/101600/5 "2025-02-03T08:43:09Z")

</div>

I am guessing when you move script to library, its trying to access the Kepware from the Gateway Server which may have different configuration than this:  
`server = connection.server(host='127.0.0.1', port=57412, user='Administrator', pw='')`

And when you call the same form button or ignition script console, it refers the Kepware from the client server.
