GeoNetwork CSW insert transaction for metadata

Since this is a bit tricky to get right and since owslib at the moment doesn't seem to support GeoNetworks new login mechanism, here an example for a CSW insert transaction request in Python which I tested successfully with GeoNetwork 2.10.3 and 3.0.1.

                #!/usr/bin/env python
                # -*- coding: latin-1 -*-
                # author:
                # purpose: csw insert of gmd:MD_Metadata XML

                import requests

                def metadata_insert(gn_url, gn_user, gn_pass, input_path):
                  '''Sends OGC CSW Transaction Insert Request to specified
                    metadata catalogue to insert gmd:MD_Metadata XML.
                    input : serverurl:port, username, password, input-file-path
                    output: insert status, insert message '''

                    gn_login_j = gn_url + '/geonetwork/j_spring_security_check'
                    gn_logout_j = gn_url + '/geonetwork/j_spring_security_logout'
                    # gn_csw_url = gn_url + '/geonetwork/srv/eng/csw'  # used e.g. for getRecords requests
                    gn_insert_url = gn_url + '/geonetwork/srv/eng/csw-publication'

                    session = requests.Session()
                    url = gn_login_j
                    params = {'username': '%s' % gn_user, 'password': '%s' % gn_pass}
                    response_login =, data=params)  # login to geonetwork
                    # print response_login.text  # debug

                    # The xml file should be IS 19139 encoded gmd:MD_Metadata
                    xml_file = open(input_path)
                    # You could download a and modify (id) a metadatset like this from Geonetwork for testing purpose.

                    xml_payload =
                    xml_insert = '''<?xml version="1.0" encoding="UTF-8"?>
                    <csw:Transaction service="CSW" version="2.0.2" xmlns:csw="">
                    </csw:Transaction>''' % (xml_payload)

                    headers = {'Content-Type': 'application/xml'}
                    response_insert =, data=xml_insert, headers=headers)  # insert metadata

          , headers={'Connection': 'close'})  # close your session

                    return(response_insert.status_code, response_insert.text)

                gn_url = ""
                gn_user = "admin"
                gn_pass = "your_password"
                input_path = './insert-test-data/deleteme.xml'

                test = metadata_insert(gn_url, gn_user, gn_pass, input_path)
                # after a successful insert you should get status 200, a transaction summary,
                # together with the identifiers of the inserted records

                for item in test:
                    print item